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(); j
++) 
 957         xpos 
+= m_owner
->GetColumnWidth( j 
); 
 959         if ((abs(x
-xpos
) < 3) && (y 
< 22) && (m_column 
< m_owner
->GetColumnCount()-1)) 
 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(); 
1064         if (!wxPendingDelete
.Member(this)) 
1065             wxPendingDelete
.Append(this); 
1067         if ((*m_accept
) && ((*m_res
) != m_startValue
)) 
1068             m_owner
->OnRenameAccept(); 
1072     if (event
.m_keyCode 
== WXK_ESCAPE
) 
1074         (*m_accept
) = FALSE
; 
1077         if (!wxPendingDelete
.Member(this)) 
1078             wxPendingDelete
.Append(this); 
1086 void wxListTextCtrl::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1088     if (!wxPendingDelete
.Member(this)) 
1089         wxPendingDelete
.Append(this); 
1091     if ((*m_accept
) && ((*m_res
) != m_startValue
)) 
1092         m_owner
->OnRenameAccept(); 
1095 //----------------------------------------------------------------------------- 
1097 //----------------------------------------------------------------------------- 
1099 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
); 
1101 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
) 
1102   EVT_PAINT          (wxListMainWindow::OnPaint
) 
1103   EVT_SIZE           (wxListMainWindow::OnSize
) 
1104   EVT_MOUSE_EVENTS   (wxListMainWindow::OnMouse
) 
1105   EVT_CHAR           (wxListMainWindow::OnChar
) 
1106   EVT_KEY_DOWN       (wxListMainWindow::OnKeyDown
) 
1107   EVT_SET_FOCUS      (wxListMainWindow::OnSetFocus
) 
1108   EVT_KILL_FOCUS     (wxListMainWindow::OnKillFocus
) 
1109   EVT_SCROLL                 (wxListMainWindow::OnScroll
) 
1112 wxListMainWindow::wxListMainWindow() 
1115     m_lines
.DeleteContents( TRUE 
); 
1116     m_columns
.DeleteContents( TRUE 
); 
1117     m_current 
= (wxListLineData 
*) NULL
; 
1119     m_hilightBrush 
= (wxBrush 
*) NULL
; 
1123     m_small_image_list 
= (wxImageList 
*) NULL
; 
1124     m_normal_image_list 
= (wxImageList 
*) NULL
; 
1125     m_small_spacing 
= 30; 
1126     m_normal_spacing 
= 40; 
1129     m_lastOnSame 
= FALSE
; 
1130     m_renameTimer 
= new wxListRenameTimer( this ); 
1131     m_isCreated 
= FALSE
; 
1135 wxListMainWindow::wxListMainWindow( wxWindow 
*parent
, wxWindowID id
, 
1136       const wxPoint 
&pos
, const wxSize 
&size
, 
1137       long style
, const wxString 
&name 
) : 
1138   wxScrolledWindow( parent
, id
, pos
, size
, style
|wxHSCROLL
|wxVSCROLL
, name 
) 
1141     m_lines
.DeleteContents( TRUE 
); 
1142     m_columns
.DeleteContents( TRUE 
); 
1143     m_current 
= (wxListLineData 
*) NULL
; 
1146     m_hilightBrush 
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID 
); 
1147     m_small_image_list 
= (wxImageList 
*) NULL
; 
1148     m_normal_image_list 
= (wxImageList 
*) NULL
; 
1149     m_small_spacing 
= 30; 
1150     m_normal_spacing 
= 40; 
1153     m_isCreated 
= FALSE
; 
1157     if (m_mode 
& wxLC_REPORT
) 
1159 #if wxUSE_GENERIC_LIST_EXTENSIONS 
1171     SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 ); 
1174     m_lastOnSame 
= FALSE
; 
1175     m_renameTimer 
= new wxListRenameTimer( this ); 
1176     m_renameAccept 
= FALSE
; 
1178     SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX 
) ); 
1181 wxListMainWindow::~wxListMainWindow() 
1185     if (m_hilightBrush
) delete m_hilightBrush
; 
1187     delete m_renameTimer
; 
1190 void wxListMainWindow::RefreshLine( wxListLineData 
*line 
) 
1192     if (m_dirty
) return; 
1200         wxClientDC 
dc(this); 
1202         line
->GetExtent( x
, y
, w
, h 
); 
1204           dc
.LogicalToDeviceX(x
-3), 
1205           dc
.LogicalToDeviceY(y
-3), 
1206           dc
.LogicalToDeviceXRel(w
+6), 
1207           dc
.LogicalToDeviceXRel(h
+6) ); 
1208         Refresh( TRUE
, &rect 
); 
1212 void wxListMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1214     // Note: a wxPaintDC must be constructed even if no drawing is 
1215     // done (a Windows requirement). 
1216     wxPaintDC 
dc( this ); 
1219     if (m_dirty
) return; 
1221     if (m_lines
.GetCount() == 0) return; 
1225     dc
.SetFont( GetFont() ); 
1227     if (m_mode 
& wxLC_REPORT
) 
1229         int lineSpacing 
= 0; 
1230         wxListLineData 
*line 
= (wxListLineData
*)m_lines
.First()->Data(); 
1232         line
->GetSize( dummy
, lineSpacing 
); 
1235         int y_s 
= m_yScroll
*GetScrollPos( wxVERTICAL 
); 
1237         wxNode 
*node 
= m_lines
.Nth( y_s 
/ lineSpacing 
); 
1238         for (int i 
= 0; i 
< m_visibleLines
+2; i
++) 
1242             line 
= (wxListLineData
*)node
->Data(); 
1244             node 
= node
->Next(); 
1249         wxNode 
*node 
= m_lines
.First(); 
1252             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
1254             node 
= node
->Next(); 
1258     if (m_current
) m_current
->DrawRubberBand( &dc
, m_hasFocus 
); 
1263 void wxListMainWindow::HilightAll( bool on 
) 
1265     wxNode 
*node 
= m_lines
.First(); 
1268         wxListLineData 
*line 
= (wxListLineData 
*)node
->Data(); 
1269         if (line
->IsHilighted() != on
) 
1271             line
->Hilight( on 
); 
1272             RefreshLine( line 
); 
1274         node 
= node
->Next(); 
1278 void wxListMainWindow::SendNotify( wxListLineData 
*line
, wxEventType command 
) 
1280     wxListEvent 
le( command
, GetParent()->GetId() ); 
1281     le
.SetEventObject( GetParent() ); 
1282     le
.m_itemIndex 
= GetIndexOfLine( line 
); 
1283     line
->GetItem( 0, le
.m_item 
); 
1284     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1285 //    GetParent()->GetEventHandler()->AddPendingEvent( le ); 
1288 void wxListMainWindow::FocusLine( wxListLineData 
*WXUNUSED(line
) ) 
1290 //  SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED ); 
1293 void wxListMainWindow::UnfocusLine( wxListLineData 
*WXUNUSED(line
) ) 
1295 //  SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED ); 
1298 void wxListMainWindow::SelectLine( wxListLineData 
*line 
) 
1300     SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_SELECTED 
); 
1303 void wxListMainWindow::DeselectLine( wxListLineData 
*line 
) 
1305     SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_DESELECTED 
); 
1308 void wxListMainWindow::DeleteLine( wxListLineData 
*line 
) 
1310     SendNotify( line
, wxEVT_COMMAND_LIST_DELETE_ITEM 
); 
1315 void wxListMainWindow::EditLabel( long item 
) 
1317     wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
1318     wxCHECK_RET( node
, wxT("wrong index in wxListCtrl::Edit()") ); 
1320     m_currentEdit 
= (wxListLineData
*) node
->Data(); 
1322     wxListEvent 
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() ); 
1323     le
.SetEventObject( GetParent() ); 
1324     le
.m_itemIndex 
= GetIndexOfLine( m_currentEdit 
); 
1325     m_currentEdit
->GetItem( 0, le
.m_item 
); 
1326     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1328     if (!le
.IsAllowed()) 
1331     // We have to call this here because the label in 
1332     // question might just have been added and no screen 
1333     // update taken place. 
1334     if (m_dirty
) wxYield(); 
1337     m_currentEdit
->GetText( 0, s 
); 
1342     m_currentEdit
->GetLabelExtent( x
, y
, w
, h 
); 
1344     wxClientDC 
dc(this); 
1346     x 
= dc
.LogicalToDeviceX( x 
); 
1347     y 
= dc
.LogicalToDeviceY( y 
); 
1349     wxListTextCtrl 
*text 
= new wxListTextCtrl( 
1350       this, -1, &m_renameAccept
, &m_renameRes
, this, s
, wxPoint(x
-4,y
-4), wxSize(w
+11,h
+8) ); 
1354 void wxListMainWindow::OnRenameTimer() 
1356     wxCHECK_RET( m_current
, wxT("invalid m_current") ); 
1358     Edit( m_lines
.IndexOf( m_current 
) ); 
1361 void wxListMainWindow::OnRenameAccept() 
1363     wxListEvent 
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() ); 
1364     le
.SetEventObject( GetParent() ); 
1365     le
.m_itemIndex 
= GetIndexOfLine( m_currentEdit 
); 
1366     m_currentEdit
->GetItem( 0, le
.m_item 
); 
1367     le
.m_item
.m_text 
= m_renameRes
; 
1368     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1370     if (!le
.IsAllowed()) return; 
1373     info
.m_mask 
= wxLIST_MASK_TEXT
; 
1374     info
.m_itemId 
= le
.m_itemIndex
; 
1375     info
.m_text 
= m_renameRes
; 
1376     info
.SetTextColour(le
.m_item
.GetTextColour()); 
1380 void wxListMainWindow::OnMouse( wxMouseEvent 
&event 
) 
1382     if (GetParent()->GetEventHandler()->ProcessEvent( event
)) return; 
1384     if (!m_current
) return; 
1385     if (m_dirty
) return; 
1386     if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() || event
.ButtonDClick()) ) return; 
1388     wxClientDC 
dc(this); 
1390     wxCoord x 
= dc
.DeviceToLogicalX( (wxCoord
)event
.GetX() ); 
1391     wxCoord y 
= dc
.DeviceToLogicalY( (wxCoord
)event
.GetY() ); 
1393     /* Did we actually hit an item ? */ 
1395     wxNode 
*node 
= m_lines
.First(); 
1396     wxListLineData 
*line 
= (wxListLineData 
*) NULL
; 
1399         line 
= (wxListLineData
*)node
->Data(); 
1400         hitResult 
= line
->IsHit( x
, y 
); 
1401         if (hitResult
) break; 
1402         line 
= (wxListLineData 
*) NULL
; 
1403         node 
= node
->Next(); 
1406     if (event
.Dragging()) 
1408         if (m_dragCount 
== 0) 
1409             m_dragStart 
= wxPoint(x
,y
); 
1413         if (m_dragCount 
!= 3) return; 
1415         int command 
= wxEVT_COMMAND_LIST_BEGIN_DRAG
; 
1416         if (event
.RightIsDown()) command 
= wxEVT_COMMAND_LIST_BEGIN_RDRAG
; 
1418         wxListEvent 
le( command
, GetParent()->GetId() ); 
1419         le
.SetEventObject( GetParent() ); 
1420         le
.m_pointDrag 
= m_dragStart
; 
1421         GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1432     if (event
.ButtonDClick()) 
1435         m_lastOnSame 
= FALSE
; 
1436         m_renameTimer
->Stop(); 
1438         SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED 
); 
1443     if (event
.LeftUp() && m_lastOnSame
) 
1446         if ((line 
== m_current
) && 
1447             (hitResult 
== wxLIST_HITTEST_ONITEMLABEL
) && 
1448             (m_mode 
& wxLC_EDIT_LABELS
)  ) 
1450             m_renameTimer
->Start( 100, TRUE 
); 
1452         m_lastOnSame 
= FALSE
; 
1456     if (event
.RightDown()) 
1458         SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK 
); 
1462     if (event
.MiddleDown()) 
1464         SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK 
); 
1468     if (event
.LeftDown()) 
1471         wxListLineData 
*oldCurrent 
= m_current
; 
1472         if (m_mode 
& wxLC_SINGLE_SEL
) 
1475             HilightAll( FALSE 
); 
1476             m_current
->ReverseHilight(); 
1477             RefreshLine( m_current 
); 
1481             if (event
.ControlDown()) 
1484                 m_current
->ReverseHilight(); 
1485                 RefreshLine( m_current 
); 
1487             else if (event
.ShiftDown()) 
1491                 int numOfCurrent 
= -1; 
1492                 node 
= m_lines
.First(); 
1495                     wxListLineData 
*test_line 
= (wxListLineData
*)node
->Data(); 
1497                     if (test_line 
== oldCurrent
) break; 
1498                     node 
= node
->Next(); 
1502                 node 
= m_lines
.First(); 
1505                     wxListLineData 
*test_line 
= (wxListLineData
*)node
->Data(); 
1507                     if (test_line 
== line
) break; 
1508                     node 
= node
->Next(); 
1511                 if (numOfLine 
< numOfCurrent
) 
1514                     numOfLine 
= numOfCurrent
; 
1518                 wxNode 
*node 
= m_lines
.Nth( numOfCurrent 
); 
1519                 for (int i 
= 0; i 
<= numOfLine
-numOfCurrent
; i
++) 
1521                     wxListLineData 
*test_line
= (wxListLineData
*)node
->Data(); 
1522                     test_line
->Hilight(TRUE
); 
1523                     RefreshLine( test_line 
); 
1524                     node 
= node
->Next(); 
1530                 HilightAll( FALSE 
); 
1531                 m_current
->ReverseHilight(); 
1532                 RefreshLine( m_current 
); 
1535         if (m_current 
!= oldCurrent
) 
1537             RefreshLine( oldCurrent 
); 
1538             UnfocusLine( oldCurrent 
); 
1539             FocusLine( m_current 
); 
1541         m_lastOnSame 
= (m_current 
== oldCurrent
); 
1546 void wxListMainWindow::MoveToFocus() 
1548     if (!m_current
) return; 
1554     m_current
->GetExtent( item_x
, item_y
, item_w
, item_h 
); 
1558     GetClientSize( &client_w
, &client_h 
); 
1560     int view_x 
= m_xScroll
*GetScrollPos( wxHORIZONTAL 
); 
1561     int view_y 
= m_yScroll
*GetScrollPos( wxVERTICAL 
); 
1563     if (m_mode 
& wxLC_REPORT
) 
1565         if (item_y
-5 < view_y 
)  
1566             Scroll( -1, (item_y
-5)/m_yScroll 
);  
1567         if (item_y
+item_h
+5 > view_y
+client_h
)  
1568             Scroll( -1, (item_y
+item_h
-client_h
+15)/m_yScroll 
); 
1572         if (item_x
-view_x 
< 5)  
1573             Scroll( (item_x
-5)/m_xScroll
, -1 ); 
1574         if (item_x
+item_w
-5 > view_x
+client_w
)  
1575             Scroll( (item_x
+item_w
-client_w
+15)/m_xScroll
, -1 ); 
1579 void wxListMainWindow::OnArrowChar( wxListLineData 
*newCurrent
, bool shiftDown 
) 
1581     if ((m_mode 
& wxLC_SINGLE_SEL
) || (m_usedKeys 
== FALSE
)) m_current
->Hilight( FALSE 
); 
1582     wxListLineData 
*oldCurrent 
= m_current
; 
1583     m_current 
= newCurrent
; 
1584     if (shiftDown 
|| (m_mode 
& wxLC_SINGLE_SEL
)) m_current
->Hilight( TRUE 
); 
1585     RefreshLine( m_current 
); 
1586     RefreshLine( oldCurrent 
); 
1587     FocusLine( m_current 
); 
1588     UnfocusLine( oldCurrent 
); 
1592 void wxListMainWindow::OnKeyDown( wxKeyEvent 
&event 
) 
1594     wxWindow 
*parent 
= GetParent(); 
1596     /* we propagate the key event up */ 
1597     wxKeyEvent 
ke( wxEVT_KEY_DOWN 
); 
1598     ke
.m_shiftDown 
= event
.m_shiftDown
; 
1599     ke
.m_controlDown 
= event
.m_controlDown
; 
1600     ke
.m_altDown 
= event
.m_altDown
; 
1601     ke
.m_metaDown 
= event
.m_metaDown
; 
1602     ke
.m_keyCode 
= event
.m_keyCode
; 
1605     ke
.SetEventObject( parent 
); 
1606     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
1611 void wxListMainWindow::OnChar( wxKeyEvent 
&event 
) 
1613     wxWindow 
*parent 
= GetParent(); 
1615     /* we send a list_key event up */ 
1616     wxListEvent 
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() ); 
1617     le
.m_code 
= (int)event
.KeyCode(); 
1618     le
.SetEventObject( parent 
); 
1619     parent
->GetEventHandler()->ProcessEvent( le 
); 
1621     /* we propagate the char event up */ 
1622     wxKeyEvent 
ke( wxEVT_CHAR 
); 
1623     ke
.m_shiftDown 
= event
.m_shiftDown
; 
1624     ke
.m_controlDown 
= event
.m_controlDown
; 
1625     ke
.m_altDown 
= event
.m_altDown
; 
1626     ke
.m_metaDown 
= event
.m_metaDown
; 
1627     ke
.m_keyCode 
= event
.m_keyCode
; 
1630     ke
.SetEventObject( parent 
); 
1631     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
1633     if (event
.KeyCode() == WXK_TAB
) 
1635         wxNavigationKeyEvent nevent
; 
1636         nevent
.SetDirection( !event
.ShiftDown() ); 
1637         nevent
.SetEventObject( GetParent()->GetParent() ); 
1638         nevent
.SetCurrentFocus( m_parent 
); 
1639         if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent 
)) return; 
1642     /* no item -> nothing to do */ 
1649     switch (event
.KeyCode()) 
1653             wxNode 
*node 
= m_lines
.Member( m_current 
)->Previous(); 
1654             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1659             wxNode 
*node 
= m_lines
.Member( m_current 
)->Next(); 
1660             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1665             wxNode 
*node 
= m_lines
.Last(); 
1666             OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1671             wxNode 
*node 
= m_lines
.First(); 
1672             OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1678             if (m_mode 
& wxLC_REPORT
) 
1680                 steps 
= m_visibleLines
-1; 
1685                 wxNode 
*node 
= m_lines
.First(); 
1686                 for (;;) { if (m_current 
== (wxListLineData
*)node
->Data()) break; pos
++; node 
= node
->Next(); } 
1687                 steps 
= pos 
% m_visibleLines
; 
1689             wxNode 
*node 
= m_lines
.Member( m_current 
); 
1690             for (int i 
= 0; i 
< steps
; i
++) if (node
->Previous()) node 
= node
->Previous(); 
1691             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1697             if (m_mode 
& wxLC_REPORT
) 
1699                 steps 
= m_visibleLines
-1; 
1703                 int pos 
= 0; wxNode 
*node 
= m_lines
.First(); 
1704                 for (;;) { if (m_current 
== (wxListLineData
*)node
->Data()) break; pos
++; node 
= node
->Next(); } 
1705                 steps 
= m_visibleLines
-(pos 
% m_visibleLines
)-1; 
1707             wxNode 
*node 
= m_lines
.Member( m_current 
); 
1708             for (int i 
= 0; i 
< steps
; i
++) if (node
->Next()) node 
= node
->Next(); 
1709             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1714             if (!(m_mode 
& wxLC_REPORT
)) 
1716                 wxNode 
*node 
= m_lines
.Member( m_current 
); 
1717                 for (int i 
= 0; i 
<m_visibleLines
; i
++) if (node
->Previous()) node 
= node
->Previous(); 
1718                 if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1724             if (!(m_mode 
& wxLC_REPORT
)) 
1726                 wxNode 
*node 
= m_lines
.Member( m_current 
); 
1727                 for (int i 
= 0; i 
<m_visibleLines
; i
++) if (node
->Next()) node 
= node
->Next(); 
1728                 if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1734             m_current
->ReverseHilight(); 
1735             RefreshLine( m_current 
); 
1740             if (!(m_mode 
& wxLC_SINGLE_SEL
)) 
1742                 wxListLineData 
*oldCurrent 
= m_current
; 
1743                 m_current
->ReverseHilight(); 
1744                 wxNode 
*node 
= m_lines
.Member( m_current 
)->Next(); 
1745                 if (node
) m_current 
= (wxListLineData
*)node
->Data(); 
1746                 RefreshLine( oldCurrent 
); 
1747                 RefreshLine( m_current 
); 
1748                 UnfocusLine( oldCurrent 
); 
1749                 FocusLine( m_current 
); 
1757             wxListEvent 
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
, GetParent()->GetId() ); 
1758             le
.SetEventObject( GetParent() ); 
1759             le
.m_itemIndex 
= GetIndexOfLine( m_current 
); 
1760             m_current
->GetItem( 0, le
.m_item 
); 
1761             GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1774 extern wxWindow 
*g_focusWindow
; 
1777 void wxListMainWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1780     RefreshLine( m_current 
); 
1782     if (!GetParent()) return; 
1785     g_focusWindow 
= GetParent(); 
1788     wxFocusEvent 
event( wxEVT_SET_FOCUS
, GetParent()->GetId() ); 
1789     event
.SetEventObject( GetParent() ); 
1790     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
1793 void wxListMainWindow::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1796     RefreshLine( m_current 
); 
1799 void wxListMainWindow::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
1802   We don't even allow the wxScrolledWindow::AdjustScrollbars() call 
1807 void wxListMainWindow::DrawImage( int index
, wxDC 
*dc
, int x
, int y 
) 
1809     if ((m_mode 
& wxLC_ICON
) && (m_normal_image_list
)) 
1811         m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1814     if ((m_mode 
& wxLC_SMALL_ICON
) && (m_small_image_list
)) 
1816         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1818     if ((m_mode 
& wxLC_LIST
) && (m_small_image_list
)) 
1820         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1822     if ((m_mode 
& wxLC_REPORT
) && (m_small_image_list
)) 
1824         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1829 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height 
) 
1831     if ((m_mode 
& wxLC_ICON
) && (m_normal_image_list
)) 
1833         m_normal_image_list
->GetSize( index
, width
, height 
); 
1836     if ((m_mode 
& wxLC_SMALL_ICON
) && (m_small_image_list
)) 
1838         m_small_image_list
->GetSize( index
, width
, height 
); 
1841     if ((m_mode 
& wxLC_LIST
) && (m_small_image_list
)) 
1843         m_small_image_list
->GetSize( index
, width
, height 
); 
1846     if ((m_mode 
& wxLC_REPORT
) && (m_small_image_list
)) 
1848         m_small_image_list
->GetSize( index
, width
, height 
); 
1855 int wxListMainWindow::GetTextLength( wxString 
&s 
) 
1857     wxClientDC 
dc( this ); 
1860     dc
.GetTextExtent( s
, &lw
, &lh 
); 
1864 int wxListMainWindow::GetIndexOfLine( const wxListLineData 
*line 
) 
1867     wxNode 
*node 
= m_lines
.First(); 
1870         if (line 
== (wxListLineData
*)node
->Data()) return i
; 
1872         node 
= node
->Next(); 
1877 void wxListMainWindow::SetImageList( wxImageList 
*imageList
, int which 
) 
1880     if (which 
== wxIMAGE_LIST_NORMAL
) m_normal_image_list 
= imageList
; 
1881     if (which 
== wxIMAGE_LIST_SMALL
) m_small_image_list 
= imageList
; 
1884 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall 
) 
1889         m_small_spacing 
= spacing
; 
1893         m_normal_spacing 
= spacing
; 
1897 int wxListMainWindow::GetItemSpacing( bool isSmall 
) 
1899     if (isSmall
) return m_small_spacing
; else return m_normal_spacing
; 
1902 void wxListMainWindow::SetColumn( int col
, wxListItem 
&item 
) 
1905     wxNode 
*node 
= m_columns
.Nth( col 
); 
1908         if (item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER
) item
.m_width 
= GetTextLength( item
.m_text 
)+7; 
1909         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1910         column
->SetItem( item 
); 
1912     wxListCtrl 
*lc 
= (wxListCtrl
*) GetParent(); 
1913     if (lc
->m_headerWin
) lc
->m_headerWin
->Refresh(); 
1916 void wxListMainWindow::SetColumnWidth( int col
, int width 
) 
1918     if (!(m_mode 
& wxLC_REPORT
)) return; 
1922     wxNode 
*node 
= (wxNode
*) NULL
; 
1924     if (width 
== wxLIST_AUTOSIZE_USEHEADER
) width 
= 80; 
1925     if (width 
== wxLIST_AUTOSIZE
) 
1927         wxClientDC 
dc(this); 
1928         dc
.SetFont( GetFont() ); 
1930         node 
= m_lines
.First(); 
1933             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
1934             wxNode 
*n 
= line
->m_items
.Nth( col 
); 
1937                 wxListItemData 
*item 
= (wxListItemData
*)n
->Data(); 
1938                 int current 
= 0, ix 
= 0, iy 
= 0; 
1939                 wxCoord lx 
= 0, ly 
= 0; 
1940                 if (item
->HasImage()) 
1942                     GetImageSize( item
->GetImage(), ix
, iy 
); 
1945                 if (item
->HasText()) 
1948                     item
->GetText( str 
); 
1949                     dc
.GetTextExtent( str
, &lx
, &ly 
); 
1952                 if (current 
> max
) max 
= current
; 
1954             node 
= node
->Next(); 
1959     node 
= m_columns
.Nth( col 
); 
1962         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1963         column
->SetWidth( width 
); 
1966     node 
= m_lines
.First(); 
1969         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
1970         wxNode 
*n 
= line
->m_items
.Nth( col 
); 
1973             wxListItemData 
*item 
= (wxListItemData
*)n
->Data(); 
1974             item
->SetSize( width
, -1 ); 
1976         node 
= node
->Next(); 
1979     wxListCtrl 
*lc 
= (wxListCtrl
*) GetParent(); 
1980     if (lc
->m_headerWin
) lc
->m_headerWin
->Refresh(); 
1983 void wxListMainWindow::GetColumn( int col
, wxListItem 
&item 
) 
1985     wxNode 
*node 
= m_columns
.Nth( col 
); 
1988         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1989         column
->GetItem( item 
); 
2001 int wxListMainWindow::GetColumnWidth( int col 
) 
2003     wxNode 
*node 
= m_columns
.Nth( col 
); 
2006         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
2007         return column
->GetWidth(); 
2015 int wxListMainWindow::GetColumnCount() 
2017     return m_columns
.Number(); 
2020 int wxListMainWindow::GetCountPerPage() 
2022     return m_visibleLines
; 
2025 void wxListMainWindow::SetItem( wxListItem 
&item 
) 
2028     wxNode 
*node 
= m_lines
.Nth( (size_t)item
.m_itemId 
); 
2031         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2032         if (m_mode 
& wxLC_REPORT
) item
.m_width 
= GetColumnWidth( item
.m_col 
)-3; 
2033         line
->SetItem( item
.m_col
, item 
); 
2037 void wxListMainWindow::SetItemState( long item
, long state
, long stateMask 
) 
2039     // m_dirty = TRUE; no recalcs needed 
2041     wxListLineData 
*oldCurrent 
= m_current
; 
2043     if (stateMask 
& wxLIST_STATE_FOCUSED
) 
2045         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2048             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2049             UnfocusLine( m_current 
); 
2051             FocusLine( m_current 
); 
2052             RefreshLine( m_current 
); 
2053             if (oldCurrent
) RefreshLine( oldCurrent 
); 
2057     if (stateMask 
& wxLIST_STATE_SELECTED
) 
2059         bool on 
= (state 
& wxLIST_STATE_SELECTED
) != 0; 
2060         if (!on 
&& (m_mode 
& wxLC_SINGLE_SEL
)) return; 
2062         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2065             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2066             if (m_mode 
& wxLC_SINGLE_SEL
) 
2068                 UnfocusLine( m_current 
); 
2070                 FocusLine( m_current 
); 
2071                 if (oldCurrent
) oldCurrent
->Hilight( FALSE 
); 
2072                 RefreshLine( m_current 
); 
2073                 if (oldCurrent
) RefreshLine( oldCurrent 
); 
2075             bool on 
= (state 
& wxLIST_STATE_SELECTED
) != 0; 
2076             if (on 
!= line
->IsHilighted()) 
2078                 line
->Hilight( on 
); 
2079                 RefreshLine( line 
); 
2085 int wxListMainWindow::GetItemState( long item
, long stateMask 
) 
2087     int ret 
= wxLIST_STATE_DONTCARE
; 
2088     if (stateMask 
& wxLIST_STATE_FOCUSED
) 
2090         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2093             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2094             if (line 
== m_current
) ret 
|= wxLIST_STATE_FOCUSED
; 
2097     if (stateMask 
& wxLIST_STATE_SELECTED
) 
2099         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2102             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2103             if (line
->IsHilighted()) ret 
|= wxLIST_STATE_FOCUSED
; 
2109 void wxListMainWindow::GetItem( wxListItem 
&item 
) 
2111     wxNode 
*node 
= m_lines
.Nth( (size_t)item
.m_itemId 
); 
2114         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2115         line
->GetItem( item
.m_col
, item 
); 
2126 int wxListMainWindow::GetItemCount() 
2128     return m_lines
.Number(); 
2131 void wxListMainWindow::GetItemRect( long index
, wxRect 
&rect 
) 
2133     wxNode 
*node 
= m_lines
.Nth( (size_t)index 
); 
2136         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2137         line
->GetRect( rect 
); 
2148 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
) 
2150     wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2154         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2155         line
->GetRect( rect 
); 
2167 int wxListMainWindow::GetSelectedItemCount() 
2170     wxNode 
*node 
= m_lines
.First(); 
2173         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2174         if (line
->IsHilighted()) ret
++; 
2175         node 
= node
->Next(); 
2180 void wxListMainWindow::SetMode( long mode 
) 
2187     if (m_mode 
& wxLC_REPORT
) 
2189 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2203 long wxListMainWindow::GetMode() const 
2208 void wxListMainWindow::CalculatePositions() 
2210     if (!m_lines
.First()) return; 
2212     wxClientDC 
dc( this ); 
2213     dc
.SetFont( GetFont() ); 
2215     int iconSpacing 
= 0; 
2216     if (m_mode 
& wxLC_ICON
) iconSpacing 
= m_normal_spacing
; 
2217     if (m_mode 
& wxLC_SMALL_ICON
) iconSpacing 
= m_small_spacing
; 
2219     // we take the first line (which also can be an icon or 
2220     // an a text item in wxLC_ICON and wxLC_LIST modes) to 
2221     // measure the size of the line 
2225     int lineSpacing 
= 0; 
2227     wxListLineData 
*line 
= (wxListLineData
*)m_lines
.First()->Data(); 
2228     line
->CalculateSize( &dc
, iconSpacing 
); 
2230     line
->GetSize( dummy
, lineSpacing 
); 
2233     int clientWidth 
= 0; 
2234     int clientHeight 
= 0; 
2236     if (m_mode 
& wxLC_REPORT
) 
2240         int entireHeight 
= m_lines
.Number() * lineSpacing 
+ 2; 
2241         int scroll_pos 
= GetScrollPos( wxVERTICAL 
); 
2242 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2243         int x_scroll_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2245         SetScrollbars( m_xScroll
, m_yScroll
, 0, (entireHeight
+15) / m_yScroll
, 0, scroll_pos
, TRUE 
); 
2247         GetClientSize( &clientWidth
, &clientHeight 
); 
2249         wxNode
* node 
= m_lines
.First(); 
2250         int entireWidth 
= 0 ; 
2253             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2254             line
->CalculateSize( &dc
, iconSpacing 
); 
2255             line
->SetPosition( &dc
, x
, y
, clientWidth 
); 
2257             for (int i 
= 0; i 
< GetColumnCount(); i
++) 
2259                 line
->SetColumnPosition( i
, col_x 
); 
2260                 col_x 
+= GetColumnWidth( i 
); 
2262             entireWidth 
= wxMax( entireWidth 
, col_x 
) ; 
2263 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2264             line
->SetPosition( &dc
, x
, y
, col_x 
); 
2266             y 
+= lineSpacing
;  // one pixel blank line between items 
2267             node 
= node
->Next(); 
2269                 m_visibleLines 
= clientHeight 
/ lineSpacing
; 
2270 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2271                 SetScrollbars( m_xScroll
, m_yScroll
, entireWidth 
/ m_xScroll 
, (entireHeight
+15) / m_yScroll
, x_scroll_pos  
, scroll_pos
, TRUE 
); 
2276         // at first we try without any scrollbar. if the items don't 
2277         // fit into the window, we recalculate after subtracting an 
2278         // approximated 15 pt for the horizontal scrollbar 
2280         GetSize( &clientWidth
, &clientHeight 
); 
2281         clientHeight 
-= 4;  // sunken frame 
2283         int entireWidth 
= 0; 
2285         for (int tries 
= 0; tries 
< 2; tries
++) 
2288             int x 
= 5;  // painting is done at x-2 
2289             int y 
= 5;  // painting is done at y-2 
2292             int m_currentVisibleLines 
= 0; 
2293             wxNode 
*node 
= m_lines
.First(); 
2296                 m_currentVisibleLines
++; 
2297                 wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2298                 line
->CalculateSize( &dc
, iconSpacing 
); 
2299                 line
->SetPosition( &dc
, x
, y
, clientWidth 
); 
2300                 line
->GetSize( lineWidth
, lineHeight 
); 
2301                 if (lineWidth 
> maxWidth
) maxWidth 
= lineWidth
; 
2303                 if (m_currentVisibleLines 
> m_visibleLines
) 
2304                     m_visibleLines 
= m_currentVisibleLines
; 
2305                 if (y
+lineSpacing
-6 >= clientHeight
) // -6 for earlier "line breaking" 
2307                     m_currentVisibleLines 
= 0; 
2310                     entireWidth 
+= maxWidth
+6; 
2313                 node 
= node
->Next(); 
2314                 if (!node
) entireWidth 
+= maxWidth
; 
2315                 if ((tries 
== 0) && (entireWidth 
> clientWidth
)) 
2317                     clientHeight 
-= 15; // scrollbar height 
2319                     m_currentVisibleLines 
= 0; 
2322                 if (!node
) tries 
= 1;  // everything fits, no second try required 
2326         int scroll_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2327         SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+15) / m_xScroll
, 0, scroll_pos
, 0, TRUE 
); 
2331 void wxListMainWindow::RealizeChanges( void ) 
2335         wxNode 
*node 
= m_lines
.First(); 
2336         if (node
) m_current 
= (wxListLineData
*)node
->Data(); 
2340         FocusLine( m_current 
); 
2341         if (m_mode 
& wxLC_SINGLE_SEL
) m_current
->Hilight( TRUE 
); 
2345 long wxListMainWindow::GetNextItem( long item
, 
2346                                     int WXUNUSED(geometry
), 
2350          max 
= GetItemCount(); 
2351     wxCHECK_MSG( (ret 
== -1) || (ret 
< max
), -1, 
2352                  _T("invalid listctrl index in GetNextItem()") ); 
2354     // notice that we start with the next item (or the first one if item == -1) 
2355     // and this is intentional to allow writing a simple loop to iterate over 
2356     // all selected items 
2360         // this is not an error because the index was ok initially, just no 
2365     wxNode 
*node 
= m_lines
.Nth( (size_t)ret 
); 
2368         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2369         if ((state 
& wxLIST_STATE_FOCUSED
) && (line 
== m_current
)) 
2371         if ((state 
& wxLIST_STATE_SELECTED
) && (line
->IsHilighted())) 
2377         node 
= node
->Next(); 
2383 void wxListMainWindow::DeleteItem( long index 
) 
2386     wxNode 
*node 
= m_lines
.Nth( (size_t)index 
); 
2389         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2390         if (m_current 
== line
) m_current 
= (wxListLineData 
*) NULL
; 
2392         m_lines
.DeleteNode( node 
); 
2396 void wxListMainWindow::DeleteColumn( int col 
) 
2398     wxCHECK_RET( col 
< (int)m_columns
.GetCount(), 
2399                wxT("attempting to delete inexistent column in wxListView") ); 
2402     wxNode 
*node 
= m_columns
.Nth( col 
); 
2403     if (node
) m_columns
.DeleteNode( node 
); 
2406 void wxListMainWindow::DeleteAllItems() 
2409     m_current 
= (wxListLineData 
*) NULL
; 
2411     // to make the deletion of all items faster, we don't send the 
2412     // notifications in this case: this is compatible with wxMSW and 
2413     // documented in DeleteAllItems() description 
2415     wxListEvent 
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() ); 
2416     event
.SetEventObject( GetParent() ); 
2417     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
2422 void wxListMainWindow::DeleteEverything() 
2429 void wxListMainWindow::EnsureVisible( long index 
) 
2431     // We have to call this here because the label in 
2432     // question might just have been added and no screen 
2433     // update taken place. 
2434     if (m_dirty
) wxYield(); 
2436     wxListLineData 
*oldCurrent 
= m_current
; 
2437     m_current 
= (wxListLineData 
*) NULL
; 
2438     wxNode 
*node 
= m_lines
.Nth( (size_t)index 
); 
2439     if (node
) m_current 
= (wxListLineData
*)node
->Data(); 
2440     if (m_current
) MoveToFocus(); 
2441     m_current 
= oldCurrent
; 
2444 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) ) 
2448     if (pos 
< 0) pos 
= 0; 
2449     wxNode 
*node 
= m_lines
.Nth( (size_t)pos 
); 
2452         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2454         line
->GetText( 0, s 
); 
2455         if (s 
== tmp
) return pos
; 
2456         node 
= node
->Next(); 
2462 long wxListMainWindow::FindItem(long start
, long data
) 
2465     if (pos 
< 0) pos 
= 0; 
2466     wxNode 
*node 
= m_lines
.Nth( (size_t)pos 
); 
2469         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2471         line
->GetItem( 0, item 
); 
2472         if (item
.m_data 
== data
) return pos
; 
2473         node 
= node
->Next(); 
2479 long wxListMainWindow::HitTest( int x
, int y
, int &flags 
) 
2481     wxNode 
*node 
= m_lines
.First(); 
2485         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2486         long ret 
= line
->IsHit( x
, y 
); 
2492         node 
= node
->Next(); 
2498 void wxListMainWindow::InsertItem( wxListItem 
&item 
) 
2502     if (m_mode 
& wxLC_REPORT
) mode 
= wxLC_REPORT
; 
2503     else if (m_mode 
& wxLC_LIST
) mode 
= wxLC_LIST
; 
2504     else if (m_mode 
& wxLC_ICON
) mode 
= wxLC_ICON
; 
2505     else if (m_mode 
& wxLC_SMALL_ICON
) mode 
= wxLC_ICON
;  // no typo 
2507     wxListLineData 
*line 
= new wxListLineData( this, mode
, m_hilightBrush 
); 
2509     if (m_mode 
& wxLC_REPORT
) 
2511         line
->InitItems( GetColumnCount() ); 
2512         item
.m_width 
= GetColumnWidth( 0 )-3; 
2516         line
->InitItems( 1 ); 
2519     line
->SetItem( 0, item 
); 
2520     if ((item
.m_itemId 
>= 0) && (item
.m_itemId 
< (int)m_lines
.GetCount())) 
2522         wxNode 
*node 
= m_lines
.Nth( (size_t)item
.m_itemId 
); 
2523         if (node
) m_lines
.Insert( node
, line 
); 
2527         m_lines
.Append( line 
); 
2531 void wxListMainWindow::InsertColumn( long col
, wxListItem 
&item 
) 
2534     if (m_mode 
& wxLC_REPORT
) 
2536         if (item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER
) item
.m_width 
= GetTextLength( item
.m_text 
); 
2537         wxListHeaderData 
*column 
= new wxListHeaderData( item 
); 
2538         if ((col 
>= 0) && (col 
< (int)m_columns
.GetCount())) 
2540             wxNode 
*node 
= m_columns
.Nth( (size_t)col 
); 
2542                  m_columns
.Insert( node
, column 
); 
2546             m_columns
.Append( column 
); 
2551 wxListCtrlCompare list_ctrl_compare_func_2
; 
2552 long              list_ctrl_compare_data
; 
2554 int LINKAGEMODE 
list_ctrl_compare_func_1( const void *arg1
, const void *arg2 
) 
2556     wxListLineData 
*line1 
= *((wxListLineData
**)arg1
); 
2557     wxListLineData 
*line2 
= *((wxListLineData
**)arg2
); 
2559     line1
->GetItem( 0, item 
); 
2560     long data1 
= item
.m_data
; 
2561     line2
->GetItem( 0, item 
); 
2562     long data2 
= item
.m_data
; 
2563     return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data 
); 
2566 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data 
) 
2568     list_ctrl_compare_func_2 
= fn
; 
2569     list_ctrl_compare_data 
= data
; 
2570     m_lines
.Sort( list_ctrl_compare_func_1 
); 
2574 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
) 
2576         wxScrolledWindow::OnScroll( event 
) ; 
2577 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2579     if (event
.GetOrientation() == wxHORIZONTAL 
&& ( m_mode 
& wxLC_REPORT 
)) 
2581             wxListCtrl
* lc 
= wxDynamicCast( GetParent() , wxListCtrl 
) ; 
2584                     lc
->m_headerWin
->Refresh() ; 
2586                         lc
->m_headerWin
->MacUpdateImmediately() ; 
2593 // ------------------------------------------------------------------------------------- 
2595 // ------------------------------------------------------------------------------------- 
2597 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
) 
2599 wxListItem::wxListItem() 
2608     m_format 
= wxLIST_FORMAT_CENTRE
; 
2614 void wxListItem::Clear() 
2623     m_format 
= wxLIST_FORMAT_CENTRE
; 
2625     m_text 
= wxEmptyString
; 
2627     if (m_attr
) delete m_attr
; 
2631 void wxListItem::ClearAttributes() 
2633     if (m_attr
) delete m_attr
; 
2637 // ------------------------------------------------------------------------------------- 
2639 // ------------------------------------------------------------------------------------- 
2641 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
) 
2643 wxListEvent::wxListEvent( wxEventType commandType
, int id 
): 
2644   wxNotifyEvent( commandType
, id 
) 
2650     m_cancelled 
= FALSE
; 
2655 void wxListEvent::CopyObject(wxObject
& object_dest
) const 
2657     wxListEvent 
*obj 
= (wxListEvent 
*)&object_dest
; 
2659     wxNotifyEvent::CopyObject(object_dest
); 
2661     obj
->m_code 
= m_code
; 
2662     obj
->m_itemIndex 
= m_itemIndex
; 
2663     obj
->m_oldItemIndex 
= m_oldItemIndex
; 
2665     obj
->m_cancelled 
= m_cancelled
; 
2666     obj
->m_pointDrag 
= m_pointDrag
; 
2667     obj
->m_item
.m_mask 
= m_item
.m_mask
; 
2668     obj
->m_item
.m_itemId 
= m_item
.m_itemId
; 
2669     obj
->m_item
.m_col 
= m_item
.m_col
; 
2670     obj
->m_item
.m_state 
= m_item
.m_state
; 
2671     obj
->m_item
.m_stateMask 
= m_item
.m_stateMask
; 
2672     obj
->m_item
.m_text 
= m_item
.m_text
; 
2673     obj
->m_item
.m_image 
= m_item
.m_image
; 
2674     obj
->m_item
.m_data 
= m_item
.m_data
; 
2675     obj
->m_item
.m_format 
= m_item
.m_format
; 
2676     obj
->m_item
.m_width 
= m_item
.m_width
; 
2678     if ( m_item
.HasAttributes() ) 
2680         obj
->m_item
.SetTextColour(m_item
.GetTextColour()); 
2684 // ------------------------------------------------------------------------------------- 
2686 // ------------------------------------------------------------------------------------- 
2688 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
) 
2690 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
) 
2691   EVT_SIZE          (wxListCtrl::OnSize
) 
2692   EVT_IDLE          (wxListCtrl::OnIdle
) 
2695 wxListCtrl::wxListCtrl() 
2697     m_imageListNormal 
= (wxImageList 
*) NULL
; 
2698     m_imageListSmall 
= (wxImageList 
*) NULL
; 
2699     m_imageListState 
= (wxImageList 
*) NULL
; 
2700     m_mainWin 
= (wxListMainWindow
*) NULL
; 
2701     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
2704 wxListCtrl::~wxListCtrl() 
2708 bool wxListCtrl::Create(wxWindow 
*parent
, 
2713                         const wxValidator 
&validator
, 
2714                         const wxString 
&name
) 
2716     m_imageListNormal 
= (wxImageList 
*) NULL
; 
2717     m_imageListSmall 
= (wxImageList 
*) NULL
; 
2718     m_imageListState 
= (wxImageList 
*) NULL
; 
2719     m_mainWin 
= (wxListMainWindow
*) NULL
; 
2720     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
2722     if ( !(style 
& (wxLC_REPORT 
| wxLC_LIST 
| wxLC_ICON
)) ) 
2724         style 
= style 
| wxLC_LIST
; 
2727     bool ret 
= wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name 
); 
2730     if (style 
& wxSUNKEN_BORDER
) 
2731         style 
-= wxSUNKEN_BORDER
; 
2733     m_mainWin 
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style 
); 
2735     if (HasFlag(wxLC_REPORT
)) 
2737         m_headerWin 
= new wxListHeaderWindow( this, -1, m_mainWin
, wxPoint(0,0), wxSize(size
.x
,23), wxTAB_TRAVERSAL 
); 
2738         if (HasFlag(wxLC_NO_HEADER
)) 
2739             m_headerWin
->Show( FALSE 
); 
2743         m_headerWin 
= (wxListHeaderWindow 
*) NULL
; 
2746     SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX 
) ); 
2751 void wxListCtrl::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
2753     /* handled in OnIdle */ 
2755     if (m_mainWin
) m_mainWin
->m_dirty 
= TRUE
; 
2758 void wxListCtrl::SetSingleStyle( long style
, bool add 
) 
2760     long flag 
= GetWindowStyle(); 
2764         if (style 
& wxLC_MASK_TYPE
)  flag 
= flag 
& ~wxLC_MASK_TYPE
; 
2765         if (style 
& wxLC_MASK_ALIGN
) flag 
= flag 
& ~wxLC_MASK_ALIGN
; 
2766         if (style 
& wxLC_MASK_SORT
) flag 
= flag 
& ~wxLC_MASK_SORT
; 
2775         if (flag 
& style
) flag 
-= style
; 
2778     SetWindowStyleFlag( flag 
); 
2781 void wxListCtrl::SetWindowStyleFlag( long flag 
) 
2785         m_mainWin
->DeleteEverything(); 
2789         GetClientSize( &width
, &height 
); 
2791         m_mainWin
->SetMode( flag 
); 
2793         if (flag 
& wxLC_REPORT
) 
2795             if (!HasFlag(wxLC_REPORT
)) 
2799                     m_headerWin 
= new wxListHeaderWindow( this, -1, m_mainWin
, 
2800                       wxPoint(0,0), wxSize(width
,23), wxTAB_TRAVERSAL 
); 
2801                     if (HasFlag(wxLC_NO_HEADER
)) 
2802                         m_headerWin
->Show( FALSE 
); 
2806                     if (flag 
& wxLC_NO_HEADER
) 
2807                         m_headerWin
->Show( FALSE 
); 
2809                         m_headerWin
->Show( TRUE 
); 
2815             if (HasFlag(wxLC_REPORT
) && !(HasFlag(wxLC_NO_HEADER
))) 
2817                 m_headerWin
->Show( FALSE 
); 
2822     wxWindow::SetWindowStyleFlag( flag 
); 
2825 bool wxListCtrl::GetColumn(int col
, wxListItem 
&item
) const 
2827     m_mainWin
->GetColumn( col
, item 
); 
2831 bool wxListCtrl::SetColumn( int col
, wxListItem
& item 
) 
2833     m_mainWin
->SetColumn( col
, item 
); 
2837 int wxListCtrl::GetColumnWidth( int col 
) const 
2839     return m_mainWin
->GetColumnWidth( col 
); 
2842 bool wxListCtrl::SetColumnWidth( int col
, int width 
) 
2844     m_mainWin
->SetColumnWidth( col
, width 
); 
2848 int wxListCtrl::GetCountPerPage() const 
2850   return m_mainWin
->GetCountPerPage();  // different from Windows ? 
2853 bool wxListCtrl::GetItem( wxListItem 
&info 
) const 
2855     m_mainWin
->GetItem( info 
); 
2859 bool wxListCtrl::SetItem( wxListItem 
&info 
) 
2861     m_mainWin
->SetItem( info 
); 
2865 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId 
) 
2868     info
.m_text 
= label
; 
2869     info
.m_mask 
= wxLIST_MASK_TEXT
; 
2870     info
.m_itemId 
= index
; 
2874         info
.m_image 
= imageId
; 
2875         info
.m_mask 
|= wxLIST_MASK_IMAGE
; 
2877     m_mainWin
->SetItem(info
); 
2881 int wxListCtrl::GetItemState( long item
, long stateMask 
) const 
2883     return m_mainWin
->GetItemState( item
, stateMask 
); 
2886 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask 
) 
2888     m_mainWin
->SetItemState( item
, state
, stateMask 
); 
2892 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) ) 
2895     info
.m_image 
= image
; 
2896     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
2897     info
.m_itemId 
= item
; 
2898     m_mainWin
->SetItem( info 
); 
2902 wxString 
wxListCtrl::GetItemText( long item 
) const 
2905     info
.m_itemId 
= item
; 
2906     m_mainWin
->GetItem( info 
); 
2910 void wxListCtrl::SetItemText( long item
, const wxString 
&str 
) 
2913     info
.m_mask 
= wxLIST_MASK_TEXT
; 
2914     info
.m_itemId 
= item
; 
2916     m_mainWin
->SetItem( info 
); 
2919 long wxListCtrl::GetItemData( long item 
) const 
2922     info
.m_itemId 
= item
; 
2923     m_mainWin
->GetItem( info 
); 
2927 bool wxListCtrl::SetItemData( long item
, long data 
) 
2930     info
.m_mask 
= wxLIST_MASK_DATA
; 
2931     info
.m_itemId 
= item
; 
2933     m_mainWin
->SetItem( info 
); 
2937 bool wxListCtrl::GetItemRect( long item
, wxRect 
&rect
,  int WXUNUSED(code
) ) const 
2939     m_mainWin
->GetItemRect( item
, rect 
); 
2943 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos 
) const 
2945     m_mainWin
->GetItemPosition( item
, pos 
); 
2949 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) ) 
2954 int wxListCtrl::GetItemCount() const 
2956     return m_mainWin
->GetItemCount(); 
2959 int wxListCtrl::GetColumnCount() const 
2961     return m_mainWin
->GetColumnCount(); 
2964 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall 
) 
2966     m_mainWin
->SetItemSpacing( spacing
, isSmall 
); 
2969 int wxListCtrl::GetItemSpacing( bool isSmall 
) const 
2971     return m_mainWin
->GetItemSpacing( isSmall 
); 
2974 int wxListCtrl::GetSelectedItemCount() const 
2976     return m_mainWin
->GetSelectedItemCount(); 
2979 wxColour 
wxListCtrl::GetTextColour() const 
2981     return GetForegroundColour(); 
2984 void wxListCtrl::SetTextColour(const wxColour
& col
) 
2986     SetForegroundColour(col
); 
2989 long wxListCtrl::GetTopItem() const 
2994 long wxListCtrl::GetNextItem( long item
, int geom
, int state 
) const 
2996     return m_mainWin
->GetNextItem( item
, geom
, state 
); 
2999 wxImageList 
*wxListCtrl::GetImageList(int which
) const 
3001     if (which 
== wxIMAGE_LIST_NORMAL
) 
3003         return m_imageListNormal
; 
3005     else if (which 
== wxIMAGE_LIST_SMALL
) 
3007         return m_imageListSmall
; 
3009     else if (which 
== wxIMAGE_LIST_STATE
) 
3011         return m_imageListState
; 
3013     return (wxImageList 
*) NULL
; 
3016 void wxListCtrl::SetImageList( wxImageList 
*imageList
, int which 
) 
3018     m_mainWin
->SetImageList( imageList
, which 
); 
3021 bool wxListCtrl::Arrange( int WXUNUSED(flag
) ) 
3026 bool wxListCtrl::DeleteItem( long item 
) 
3028     m_mainWin
->DeleteItem( item 
); 
3032 bool wxListCtrl::DeleteAllItems() 
3034     m_mainWin
->DeleteAllItems(); 
3038 bool wxListCtrl::DeleteAllColumns() 
3040     for ( size_t n 
= 0; n 
< m_mainWin
->m_columns
.GetCount(); n
++ ) 
3046 void wxListCtrl::ClearAll() 
3048     m_mainWin
->DeleteEverything(); 
3051 bool wxListCtrl::DeleteColumn( int col 
) 
3053     m_mainWin
->DeleteColumn( col 
); 
3057 void wxListCtrl::Edit( long item 
) 
3059     m_mainWin
->Edit( item 
); 
3062 bool wxListCtrl::EnsureVisible( long item 
) 
3064     m_mainWin
->EnsureVisible( item 
); 
3068 long wxListCtrl::FindItem( long start
, const wxString
& str
,  bool partial 
) 
3070     return m_mainWin
->FindItem( start
, str
, partial 
); 
3073 long wxListCtrl::FindItem( long start
, long data 
) 
3075     return m_mainWin
->FindItem( start
, data 
); 
3078 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
), 
3079                            int WXUNUSED(direction
)) 
3084 long wxListCtrl::HitTest( const wxPoint 
&point
, int &flags 
) 
3086     return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags 
); 
3089 long wxListCtrl::InsertItem( wxListItem
& info 
) 
3091     m_mainWin
->InsertItem( info 
); 
3092     return info
.m_itemId
; 
3095 long wxListCtrl::InsertItem( long index
, const wxString 
&label 
) 
3098     info
.m_text 
= label
; 
3099     info
.m_mask 
= wxLIST_MASK_TEXT
; 
3100     info
.m_itemId 
= index
; 
3101     return InsertItem( info 
); 
3104 long wxListCtrl::InsertItem( long index
, int imageIndex 
) 
3107     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
3108     info
.m_image 
= imageIndex
; 
3109     info
.m_itemId 
= index
; 
3110     return InsertItem( info 
); 
3113 long wxListCtrl::InsertItem( long index
, const wxString 
&label
, int imageIndex 
) 
3116     info
.m_text 
= label
; 
3117     info
.m_image 
= imageIndex
; 
3118     info
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_IMAGE
; 
3119     info
.m_itemId 
= index
; 
3120     return InsertItem( info 
); 
3123 long wxListCtrl::InsertColumn( long col
, wxListItem 
&item 
) 
3125     wxASSERT( m_headerWin 
); 
3126     m_mainWin
->InsertColumn( col
, item 
); 
3127     m_headerWin
->Refresh(); 
3132 long wxListCtrl::InsertColumn( long col
, const wxString 
&heading
, 
3133                                int format
, int width 
) 
3136     item
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_FORMAT
; 
3137     item
.m_text 
= heading
; 
3140         item
.m_mask 
|= wxLIST_MASK_WIDTH
; 
3141         item
.m_width 
= width
; 
3143     item
.m_format 
= format
; 
3145     return InsertColumn( col
, item 
); 
3148 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) ) 
3154 // fn is a function which takes 3 long arguments: item1, item2, data. 
3155 // item1 is the long data associated with a first item (NOT the index). 
3156 // item2 is the long data associated with a second item (NOT the index). 
3157 // data is the same value as passed to SortItems. 
3158 // The return value is a negative number if the first item should precede the second 
3159 // item, a positive number of the second item should precede the first, 
3160 // or zero if the two items are equivalent. 
3161 // data is arbitrary data to be passed to the sort function. 
3163 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data 
) 
3165     m_mainWin
->SortItems( fn
, data 
); 
3169 void wxListCtrl::OnIdle( wxIdleEvent 
&WXUNUSED(event
) ) 
3171     if (!m_mainWin
->m_dirty
) return; 
3175     GetClientSize( &cw
, &ch 
); 
3182     if (HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
)) 
3184         m_headerWin
->GetPosition( &x
, &y 
); 
3185         m_headerWin
->GetSize( &w
, &h 
); 
3186         if ((x 
!= 0) || (y 
!= 0) || (w 
!= cw
) || (h 
!= 23)) 
3187             m_headerWin
->SetSize( 0, 0, cw
, 23 ); 
3189         m_mainWin
->GetPosition( &x
, &y 
); 
3190         m_mainWin
->GetSize( &w
, &h 
); 
3191         if ((x 
!= 0) || (y 
!= 24) || (w 
!= cw
) || (h 
!= ch
-24)) 
3192             m_mainWin
->SetSize( 0, 24, cw
, ch
-24 ); 
3196         m_mainWin
->GetPosition( &x
, &y 
); 
3197         m_mainWin
->GetSize( &w
, &h 
); 
3198         if ((x 
!= 0) || (y 
!= 24) || (w 
!= cw
) || (h 
!= ch
)) 
3199             m_mainWin
->SetSize( 0, 0, cw
, ch 
); 
3202     m_mainWin
->CalculatePositions(); 
3203     m_mainWin
->RealizeChanges(); 
3204     m_mainWin
->m_dirty 
= FALSE
; 
3205     m_mainWin
->Refresh(); 
3208 bool wxListCtrl::SetBackgroundColour( const wxColour 
&colour 
) 
3210     if ( !wxWindow::SetBackgroundColour( colour 
) ) 
3215         m_mainWin
->SetBackgroundColour( colour 
); 
3216         m_mainWin
->m_dirty 
= TRUE
; 
3221 //        m_headerWin->SetBackgroundColour( colour ); 
3227 bool wxListCtrl::SetForegroundColour( const wxColour 
&colour 
) 
3229     if ( !wxWindow::SetForegroundColour( colour 
) ) 
3234         m_mainWin
->SetForegroundColour( colour 
); 
3235         m_mainWin
->m_dirty 
= TRUE
; 
3240         m_headerWin
->SetForegroundColour( colour 
); 
3246 bool wxListCtrl::SetFont( const wxFont 
&font 
) 
3248     if ( !wxWindow::SetFont( font 
) ) 
3253         m_mainWin
->SetFont( font 
); 
3254         m_mainWin
->m_dirty 
= TRUE
; 
3259         m_headerWin
->SetFont( font 
);