1 /////////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "listbox.h" 
  17 #include "wx/listbox.h" 
  18 #include "wx/button.h" 
  19 #include "wx/settings.h" 
  20 #include "wx/toplevel.h" 
  21 #include "wx/dynarray.h" 
  26 #if !USE_SHARED_LIBRARY 
  27 IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControl
) 
  29 BEGIN_EVENT_TABLE(wxListBox
, wxControl
) 
  31     EVT_SIZE( wxListBox::OnSize 
) 
  32     EVT_CHAR( wxListBox::OnChar 
) 
  37 #include "wx/mac/uma.h" 
  39 const short kTextColumnId 
= 1024 ; 
  41 // new databrowserbased version 
  42 // because of the limited insert 
  43 // functionality of DataBrowser,  
  44 // we just introduce id s corresponding 
  48 wxListBox::wxListBox() 
  55 bool wxListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  58                        const wxArrayString
& choices
, 
  60                        const wxValidator
& validator
, 
  63     wxCArrayString 
chs(choices
); 
  65     return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), 
  66                   style
, validator
, name
); 
  69 #if TARGET_API_MAC_OSX 
  70 static pascal void DataBrowserItemNotificationProc(ControlRef browser
, DataBrowserItemID itemID
,  
  71     DataBrowserItemNotification message
, DataBrowserItemDataRef itemData
) 
  73 static pascal  void DataBrowserItemNotificationProc(ControlRef browser
, DataBrowserItemID itemID
,  
  74     DataBrowserItemNotification message
) 
  77     long ref 
= GetControlReference( browser 
) ; 
  80         wxListBox
* list 
= wxDynamicCast( (wxObject
*) ref 
, wxListBox 
) ; 
  82         if (i 
>= 0 && i 
< list
->GetCount() ) 
  84             bool trigger 
= false ; 
  86                 wxEVT_COMMAND_LISTBOX_SELECTED
, list
->GetId() ); 
  89                 case kDataBrowserItemDeselected 
: 
  90                     if ( list
->HasMultipleSelection() ) 
  93                 case kDataBrowserItemSelected 
: 
  96                 case kDataBrowserItemDoubleClicked 
: 
  97                     event
.SetEventType(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
) ; 
 105                 event
.SetEventObject( list 
); 
 106                 if ( list
->HasClientObjectData() ) 
 107                     event
.SetClientObject( list
->GetClientObject(i
) ); 
 108                 else if ( list
->HasClientUntypedData() ) 
 109                     event
.SetClientData( list
->GetClientData(i
) ); 
 110                 event
.SetString( list
->GetString(i
) ); 
 112                 event
.SetExtraLong( list
->HasMultipleSelection() ? message 
== kDataBrowserItemSelected 
: TRUE 
); 
 113                 wxPostEvent( list
->GetEventHandler() , event 
) ; 
 114                 // direct notification is not always having the listbox GetSelection() having in synch with event 
 115                 // list->GetEventHandler()->ProcessEvent(event) ;  
 122 static pascal OSStatus 
ListBoxGetSetItemData(ControlRef browser
,  
 123     DataBrowserItemID itemID
, DataBrowserPropertyID property
,  
 124     DataBrowserItemDataRef itemData
, Boolean changeValue
) 
 126         OSStatus err 
= errDataBrowserPropertyNotSupported
; 
 135                     long ref 
= GetControlReference( browser 
) ; 
 138                         wxListBox
* list 
= wxDynamicCast( (wxObject
*) ref 
, wxListBox 
) ; 
 140                     if (i 
>= 0 && i 
< list
->GetCount() ) 
 142                                 wxMacCFStringHolder 
cf( list
->GetString(i
) , list
->GetFont().GetEncoding() ) ; 
 143                                 verify_noerr( ::SetDataBrowserItemDataText( itemData 
, cf 
) ) ; 
 158 bool wxListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 161                        int n
, const wxString choices
[], 
 163                        const wxValidator
& validator
, 
 164                        const wxString
& name
) 
 166     m_macIsUserPane 
= FALSE 
; 
 168     wxASSERT_MSG( !(style 
& wxLB_MULTIPLE
) || !(style 
& wxLB_EXTENDED
), 
 169                   _T("only one of listbox selection modes can be specified") ); 
 171     if ( !wxListBoxBase::Create(parent
, id
, pos
, size
, style 
& ~(wxHSCROLL
|wxVSCROLL
), validator
, name
) ) 
 174     m_noItems 
= 0 ; // this will be increased by our append command 
 177     Rect bounds 
= wxMacGetBoundsForControl( this , pos 
, size 
) ; 
 179     m_peer 
= new wxMacControl() ; 
 180     verify_noerr( ::CreateDataBrowserControl( MAC_WXHWND(parent
->MacGetTopLevelWindowRef()), &bounds
, kDataBrowserListView 
, m_peer
->GetControlRefAddr() ) ); 
 182     DataBrowserSelectionFlags  options 
= kDataBrowserDragSelect 
; 
 183     if ( style 
& wxLB_MULTIPLE 
) 
 185         options 
+= kDataBrowserAlwaysExtendSelection 
+ kDataBrowserCmdTogglesSelection  
; 
 187     else if ( style 
& wxLB_EXTENDED 
) 
 193         options 
+= kDataBrowserSelectOnlyOne 
; 
 195     verify_noerr(m_peer
->SetSelectionFlags( options 
) );  
 197     DataBrowserListViewColumnDesc columnDesc 
; 
 198     columnDesc
.headerBtnDesc
.titleOffset 
= 0; 
 199         columnDesc
.headerBtnDesc
.version 
= kDataBrowserListViewLatestHeaderDesc
; 
 201         columnDesc
.headerBtnDesc
.btnFontStyle
.flags     
=  
 202                 kControlUseFontMask 
| kControlUseJustMask
; 
 204         columnDesc
.headerBtnDesc
.btnContentInfo
.contentType 
= kControlNoContent
; 
 205         columnDesc
.propertyDesc
.propertyType 
= kDataBrowserTextType
; 
 206         columnDesc
.headerBtnDesc
.btnFontStyle
.just 
= teFlushDefault
; 
 207         columnDesc
.headerBtnDesc
.minimumWidth 
= 0; 
 208         columnDesc
.headerBtnDesc
.maximumWidth 
= 10000; 
 210         columnDesc
.headerBtnDesc
.btnFontStyle
.font 
= kControlFontViewSystemFont
; 
 211         columnDesc
.headerBtnDesc
.btnFontStyle
.style 
= normal
; 
 212         columnDesc
.headerBtnDesc
.titleString 
= NULL 
; // CFSTR( "" ); 
 214         columnDesc
.propertyDesc
.propertyID 
= kTextColumnId
; 
 215         columnDesc
.propertyDesc
.propertyType 
= kDataBrowserTextType
; 
 216         columnDesc
.propertyDesc
.propertyFlags 
= 
 217 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 
 218          kDataBrowserListViewTypeSelectColumn 
|  
 220          kDataBrowserTableViewSelectionColumn 
; 
 223         verify_noerr(m_peer
->AddListViewColumn( &columnDesc
, kDataBrowserListViewAppendColumn
) ) ; 
 224     verify_noerr(m_peer
->AutoSizeListViewColumns() ) ; 
 225     verify_noerr(m_peer
->SetHasScrollBars(false , true ) ) ; 
 226     verify_noerr(m_peer
->SetTableViewHiliteStyle(kDataBrowserTableViewFillHilite  
) ) ; 
 227     verify_noerr(m_peer
->SetListViewHeaderBtnHeight( 0 ) ) ; 
 228     DataBrowserCallbacks callbacks 
; 
 230     callbacks
.version 
= kDataBrowserLatestCallbacks
; 
 232     InitDataBrowserCallbacks(&callbacks
); 
 234     callbacks
.u
.v1
.itemDataCallback 
=  
 235         NewDataBrowserItemDataUPP(ListBoxGetSetItemData
); 
 237         callbacks
.u
.v1
.itemNotificationCallback 
= 
 238 #if TARGET_API_MAC_OSX 
 239             (DataBrowserItemNotificationUPP
) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc
) ; 
 241             NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc
) ; 
 243     m_peer
->SetCallbacks( &callbacks
); 
 245 #if TARGET_API_MAC_OSX 
 246     // there is a redraw bug in 10.2.X 
 247     if ( UMAGetSystemVersion() < 0x1030 ) 
 248         m_peer
->SetData( kControlNoPart
, kControlDataBrowserIncludesFrameAndFocusTag
, (Boolean
) false ) ; 
 251     MacPostControlCreate(pos
,size
) ; 
 253     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 255         Append( choices
[i
] ) ; 
 258     SetBestSize(size
);   // Needed because it is a wxControlWithItems 
 263 wxListBox::~wxListBox() 
 265     m_peer
->SetReference( NULL 
) ; 
 267     // avoid access during destruction 
 274 void wxListBox::FreeData() 
 276 #if wxUSE_OWNER_DRAWN 
 277     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 279         size_t uiCount 
= m_aItems
.Count(); 
 280         while ( uiCount
-- != 0 ) { 
 281             delete m_aItems
[uiCount
]; 
 282             m_aItems
[uiCount
] = NULL
; 
 288 #endif // wxUSE_OWNER_DRAWN 
 289     if ( HasClientObjectData() ) 
 291         for ( size_t n 
= 0; n 
< (size_t)m_noItems
; n
++ ) 
 293             delete GetClientObject(n
); 
 298 void  wxListBox::DoSetSize(int x
, int y
, 
 299             int width
, int height
, 
 302     wxControl::DoSetSize( x 
, y 
, width 
, height 
, sizeFlags 
) ; 
 305 void wxListBox::DoSetFirstItem(int N
) 
 310 void wxListBox::Delete(int N
) 
 312     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 313                  wxT("invalid index in wxListBox::Delete") ); 
 315 #if wxUSE_OWNER_DRAWN 
 317     m_aItems
.RemoveAt(N
); 
 318 #else // !wxUSE_OWNER_DRAWN 
 319     if ( HasClientObjectData() ) 
 321         delete GetClientObject(N
); 
 323 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 324     m_stringArray
.RemoveAt( N 
) ; 
 325     m_dataArray
.RemoveAt( N 
) ; 
 331 int wxListBox::DoAppend(const wxString
& item
) 
 333     InvalidateBestSize(); 
 335     int index 
= m_noItems 
; 
 336     m_stringArray
.Add( item 
) ; 
 337     m_dataArray
.Add( NULL 
); 
 339     DoSetItemClientData( index 
, NULL 
) ; 
 345 void wxListBox::DoSetItems(const wxArrayString
& choices
, void** clientData
) 
 348     int n 
= choices
.GetCount(); 
 350     for( int i 
= 0 ; i 
< n 
; ++i 
) 
 354 #if wxUSE_OWNER_DRAWN 
 355             wxASSERT_MSG(clientData
[i
] == NULL
, 
 356                 wxT("Can't use client data with owner-drawn listboxes")); 
 357 #else // !wxUSE_OWNER_DRAWN 
 358             Append( choices
[i
] , clientData
[i
] ) ; 
 362             Append( choices
[i
] ) ; 
 365 #if wxUSE_OWNER_DRAWN 
 366     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) { 
 367         // first delete old items 
 368         size_t ui 
= m_aItems
.Count(); 
 369         while ( ui
-- != 0 ) { 
 375         // then create new ones 
 376         for ( ui 
= 0; ui 
< (size_t)m_noItems
; ui
++ ) { 
 377             wxOwnerDrawn 
*pNewItem 
= CreateItem(ui
); 
 378             pNewItem
->SetName(choices
[ui
]); 
 379             m_aItems
.Add(pNewItem
); 
 382 #endif // wxUSE_OWNER_DRAWN 
 385 int wxListBox::FindString(const wxString
& s
) const 
 388     if ( s
.Right(1) == wxT("*") ) 
 390         wxString search 
= s
.Left( s
.Length() - 1 ) ; 
 391         int len 
= search
.Length() ; 
 393         wxMacStringToPascal( search 
, s2 
) ; 
 395         for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 397                 wxMacStringToPascal( m_stringArray
[i
].Left( len 
) , s1 
) ; 
 399             if ( EqualString( s1 
, s2 
, false , false ) ) 
 402         if ( s
.Left(1) == wxT("*") && s
.Length() > 1 ) 
 406             for ( int i 
= 0 ; i 
< m_noItems 
; ++i 
) 
 408                 if ( GetString(i
).Lower().Matches(st
) ) 
 418         wxMacStringToPascal( s 
, s2 
) ; 
 420         for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 422                 wxMacStringToPascal( m_stringArray
[i
] , s1 
) ; 
 424             if ( EqualString( s1 
, s2 
, false , false ) ) 
 431 void wxListBox::Clear() 
 435     m_stringArray
.Empty() ; 
 436     m_dataArray
.Empty() ; 
 440 void wxListBox::SetSelection(int N
, bool select
) 
 442     if ( N 
== wxNOT_FOUND 
) 
 444         // unselect everything 
 445         int sel 
= MacGetSelection() ; 
 446         if ( sel 
!= wxNOT_FOUND 
) 
 448             UInt32 id 
= sel 
+ 1 ; 
 450                 m_peer
->SetSelectedItems( 1 , & id 
, kDataBrowserItemsRemove 
) 
 457     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 458         wxT("invalid index in wxListBox::SetSelection") ); 
 459     MacSetSelection( N 
, select 
) ; 
 460     GetSelections( m_selectionPreImage 
) ; 
 463 bool wxListBox::IsSelected(int N
) const 
 465     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, FALSE
, 
 466         wxT("invalid index in wxListBox::Selected") ); 
 468     return MacIsSelected( N 
) ; 
 471 void *wxListBox::DoGetItemClientData(int N
) const 
 473     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, NULL
, 
 474         wxT("invalid index in wxListBox::GetClientData")); 
 476     return (void *)m_dataArray
[N
]; 
 479 wxClientData 
*wxListBox::DoGetItemClientObject(int N
) const 
 481     return (wxClientData 
*) DoGetItemClientData( N 
) ; 
 484 void wxListBox::DoSetItemClientData(int N
, void *Client_data
) 
 486     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 487         wxT("invalid index in wxListBox::SetClientData") ); 
 489 #if wxUSE_OWNER_DRAWN 
 490     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 492         // client data must be pointer to wxOwnerDrawn, otherwise we would crash 
 493         // in OnMeasure/OnDraw. 
 494         wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); 
 496 #endif // wxUSE_OWNER_DRAWN 
 497     wxASSERT_MSG( m_dataArray
.GetCount() >= (size_t) N 
, wxT("invalid client_data array") ) ; 
 499     if ( m_dataArray
.GetCount() > (size_t) N 
) 
 501         m_dataArray
[N
] = (char*) Client_data 
; 
 505         m_dataArray
.Add( (char*) Client_data 
) ; 
 509 void wxListBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 511     DoSetItemClientData(n
, clientData
); 
 514 // Return number of selections and an array of selected integers 
 515 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const 
 517     return MacGetSelections( aSelections 
) ; 
 520 // Get single selection, for single choice list items 
 521 int wxListBox::GetSelection() const 
 523     return MacGetSelection() ; 
 526 // Find string for position 
 527 wxString 
wxListBox::GetString(int N
) const 
 529         return m_stringArray
[N
]  ; 
 532 void wxListBox::DoInsertItems(const wxArrayString
& items
, int pos
) 
 534     wxCHECK_RET( pos 
>= 0 && pos 
<= m_noItems
, 
 535         wxT("invalid index in wxListBox::InsertItems") ); 
 537     InvalidateBestSize(); 
 539     int nItems 
= items
.GetCount(); 
 541     for ( int i 
= 0 ; i 
< nItems 
; i
++ ) 
 543         m_stringArray
.Insert( items
[i
] , pos 
+ i 
) ; 
 544         m_dataArray
.Insert( NULL 
, pos 
+ i 
) ; 
 546         MacInsert( pos 
+ i 
, items
[i
] ) ; 
 550 void wxListBox::SetString(int N
, const wxString
& s
) 
 552     m_stringArray
[N
] = s 
; 
 556 wxSize 
wxListBox::DoGetBestSize() const 
 558     int lbWidth 
= 100;  // some defaults 
 563         wxMacPortStateHelper 
st( UMAGetWindowPort( (WindowRef
) MacGetTopLevelWindowRef() ) ) ;  
 567             ::TextFont( m_font
.MacGetFontNum() ) ; 
 568             ::TextSize( m_font
.MacGetFontSize() ) ; 
 569             ::TextFace( m_font
.MacGetFontStyle() ) ; 
 573             ::TextFont( kFontIDMonaco 
) ; 
 578         // Find the widest line 
 579         for(int i 
= 0; i 
< GetCount(); i
++) { 
 580             wxString 
str(GetString(i
)); 
 584             ::GetThemeTextDimensions( wxMacCFStringHolder( str 
, m_font
.GetEncoding() ) , 
 585                 kThemeCurrentPortFont
, 
 592             wLine 
= ::TextWidth( str
.c_str() , 0 , str
.Length() ) ; 
 594             lbWidth 
= wxMax(lbWidth
, wLine
); 
 597         // Add room for the scrollbar 
 598         lbWidth 
+= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
); 
 600         // And just a bit more 
 602         int cx 
= ::TextWidth( "X" , 0 , 1 ) ; 
 605         // don't make the listbox too tall (limit height to around 10 items) but don't 
 606         // make it too small neither 
 607         lbHeight 
= (cy
+4) * wxMin(wxMax(GetCount(), 3), 10); 
 610     return wxSize(lbWidth
, lbHeight
); 
 613 int wxListBox::GetCount() const 
 618 void wxListBox::Refresh(bool eraseBack
, const wxRect 
*rect
) 
 620     wxControl::Refresh( eraseBack 
, rect 
) ; 
 621     //    MacRedrawControl() ; 
 624 #if wxUSE_OWNER_DRAWN 
 626 class wxListBoxItem 
: public wxOwnerDrawn
 
 629     wxListBoxItem(const wxString
& str 
= ""); 
 632 wxListBoxItem::wxListBoxItem(const wxString
& str
) : wxOwnerDrawn(str
, FALSE
) 
 634     // no bitmaps/checkmarks 
 638 wxOwnerDrawn 
*wxListBox::CreateItem(size_t n
) 
 640     return new wxListBoxItem(); 
 643 #endif  //USE_OWNER_DRAWN 
 646 // Some custom controls depend on this 
 647 /* static */ wxVisualAttributes
 
 648 wxListBox::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 650     wxVisualAttributes attr
; 
 651     attr
.colFg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
); 
 652     attr
.colBg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX
); 
 653     attr
.font  
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 657 // ============================================================================ 
 658 // list box control implementation 
 659 // ============================================================================ 
 661 void wxListBox::MacDelete( int N 
) 
 663     UInt32 id 
= m_noItems
+1 ; 
 664     verify_noerr( m_peer
->RemoveItems( kDataBrowserNoItem 
, 1 , (UInt32
*) &id 
, kDataBrowserItemNoProperty 
) ) ; 
 665     verify_noerr( m_peer
->UpdateItems( kDataBrowserNoItem 
, 1 , (UInt32
*) kDataBrowserNoItem 
, kDataBrowserItemNoProperty 
, kDataBrowserItemNoProperty 
) ) ; 
 668 void wxListBox::MacInsert( int n 
, const wxString
& text
) 
 670     UInt32 id 
= m_noItems 
; // this has already been increased 
 671     verify_noerr( m_peer
->AddItems( kDataBrowserNoItem 
, 1 ,  (UInt32
*) &id 
, kDataBrowserItemNoProperty 
) ) ; 
 672     verify_noerr( m_peer
->UpdateItems( kDataBrowserNoItem 
, 1 , (UInt32
*) kDataBrowserNoItem 
, kDataBrowserItemNoProperty 
, kDataBrowserItemNoProperty 
) ) ; 
 675 void wxListBox::MacAppend( const wxString
& text
) 
 677     UInt32 id 
= m_noItems 
; // this has already been increased 
 678     verify_noerr( m_peer
->AddItems( kDataBrowserNoItem 
, 1 ,  (UInt32
*) &id 
, kDataBrowserItemNoProperty 
) ) ; 
 681 void wxListBox::MacClear() 
 683     verify_noerr( m_peer
->RemoveItems( kDataBrowserNoItem 
, 0 , NULL 
, kDataBrowserItemNoProperty 
) ) ; 
 686 void wxListBox::MacSetSelection( int n 
, bool select 
) 
 689     if ( !(GetWindowStyle() & (wxLB_MULTIPLE
|wxLB_EXTENDED
) ) ) 
 691         int n 
= MacGetSelection() ; 
 694             UInt32 idOld 
= n 
+ 1 ; 
 695             m_peer
->SetSelectedItems( 1 , & idOld 
, kDataBrowserItemsRemove 
) ; 
 698     if ( m_peer
->IsItemSelected( id 
) != select 
) 
 700         verify_noerr(m_peer
->SetSelectedItems( 1 , & id 
, kDataBrowserItemsToggle 
) ) ; 
 705 bool wxListBox::MacIsSelected( int n 
) const 
 707     return m_peer
->IsItemSelected( n 
+ 1 ) ; 
 710 int wxListBox::MacGetSelection() const 
 712     for ( int i 
= 0 ; i 
< GetCount() ; ++i 
) 
 714         if ( m_peer
->IsItemSelected( i 
+ 1 ) ) 
 722 int wxListBox::MacGetSelections( wxArrayInt
& aSelections 
) const 
 727     for ( int i 
= 0 ; i 
< GetCount() ; ++i 
) 
 729         if ( m_peer
->IsItemSelected( i 
+ 1 ) ) 
 731             aSelections
.Add( i 
) ; 
 738 void wxListBox::MacSet( int n 
, const wxString
& text 
) 
 740     // as we don't store the strings we only have to issue a redraw 
 742     verify_noerr( m_peer
->UpdateItems( kDataBrowserNoItem 
, 1 , &id 
, kDataBrowserItemNoProperty 
, kDataBrowserItemNoProperty 
) ) ; 
 745 void wxListBox::MacScrollTo( int n 
) 
 748     verify_noerr(  m_peer
->RevealItem( id 
, kTextColumnId 
, kDataBrowserRevealWithoutSelecting 
) ) ; 
 751 #if !TARGET_API_MAC_OSX 
 752 void wxListBox::OnSize( wxSizeEvent 
&event
) 
 757 void wxListBox::MacSetRedraw( bool doDraw 
) 
 759     // nothing to do in compositing mode 
 762 void wxListBox::MacDoClick() 
 764     wxArrayInt aSelections; 
 766     size_t count = GetSelections(aSelections); 
 768     if ( count == m_selectionPreImage.GetCount() ) 
 770         bool hasChanged = false ; 
 771         for ( size_t i = 0 ; i < count ; ++i ) 
 773             if ( aSelections[i] != m_selectionPreImage[i] ) 
 785     m_selectionPreImage = aSelections; 
 787     wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId); 
 788     event.SetEventObject( this ); 
 793         if ( HasClientObjectData() ) 
 794             event.SetClientObject( GetClientObject(n) ); 
 795         else if ( HasClientUntypedData() ) 
 796             event.SetClientData( GetClientData(n) ); 
 797         event.SetString( GetString(n) ); 
 804     event.m_commandInt = n; 
 806     GetEventHandler()->ProcessEvent(event); 
 810 void wxListBox::MacDoDoubleClick() 
 813     wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId); 
 814     event.SetEventObject( this ); 
 815     GetEventHandler()->ProcessEvent(event) ; 
 819 #if !TARGET_API_MAC_OSX 
 821 void wxListBox::OnChar(wxKeyEvent
& event
) 
 823     // todo trigger proper events here 
 827     if ( event
.GetKeyCode() == WXK_RETURN 
|| event
.GetKeyCode() == WXK_NUMPAD_ENTER
) 
 829         wxWindow
* parent 
= GetParent() ; 
 830         while( parent  
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL 
) 
 831             parent 
= parent
->GetParent() ; 
 833         if ( parent 
&& parent
->GetDefaultItem() ) 
 835             wxButton 
*def 
= wxDynamicCast(parent
->GetDefaultItem(), 
 837             if ( def 
&& def
->IsEnabled() ) 
 839                 wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() ); 
 840                 event
.SetEventObject(def
); 
 847     /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */ 
 848     else if (event
.GetKeyCode() == WXK_ESCAPE 
|| (event
.GetKeyCode() == '.' && event
.MetaDown() ) ) 
 850         // FIXME: look in ancestors, not just parent. 
 851         wxWindow
* win 
= GetParent()->FindWindow( wxID_CANCEL 
) ; 
 854                 wxCommandEvent 
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
); 
 855                 new_event
.SetEventObject( win 
); 
 856                 win
->GetEventHandler()->ProcessEvent( new_event 
); 
 859     else if ( event
.GetKeyCode() == WXK_TAB 
) 
 861         wxNavigationKeyEvent new_event
; 
 862         new_event
.SetEventObject( this ); 
 863         new_event
.SetDirection( !event
.ShiftDown() ); 
 864         /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */ 
 865         new_event
.SetWindowChange( event
.ControlDown() ); 
 866         new_event
.SetCurrentFocus( this ); 
 867         if ( !GetEventHandler()->ProcessEvent( new_event 
) ) 
 870     else if ( event
.GetKeyCode() == WXK_DOWN 
|| event
.GetKeyCode() == WXK_UP 
) 
 872         // perform the default key handling first 
 873         wxControl::OnKeyDown( event 
) ; 
 875         wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, m_windowId
); 
 876         event
.SetEventObject( this ); 
 878         wxArrayInt aSelections
; 
 879         int n
, count 
= GetSelections(aSelections
); 
 883             if ( HasClientObjectData() ) 
 884                 event
.SetClientObject( GetClientObject(n
) ); 
 885             else if ( HasClientUntypedData() ) 
 886                 event
.SetClientData( GetClientData(n
) ); 
 887             event
.SetString( GetString(n
) ); 
 894         event
.m_commandInt 
= n
; 
 896         GetEventHandler()->ProcessEvent(event
); 
 900         if ( event
.GetTimestamp() > m_lastTypeIn 
+ 60 ) 
 902             m_typeIn 
= wxEmptyString 
; 
 904         m_lastTypeIn 
= event
.GetTimestamp() ; 
 905         m_typeIn 
+= (char) event
.GetKeyCode() ; 
 906         int line 
= FindString(wxT("*")+m_typeIn
+wxT("*")) ; 
 909             if ( GetSelection() != line 
) 
 912                 wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, m_windowId
); 
 913                 event
.SetEventObject( this ); 
 915                 if ( HasClientObjectData() ) 
 916                     event
.SetClientObject( GetClientObject( line 
) ); 
 917                 else if ( HasClientUntypedData() ) 
 918                     event
.SetClientData( GetClientData(line
) ); 
 919                 event
.SetString( GetString(line
) ); 
 921                 event
.m_commandInt 
= line 
; 
 923                 GetEventHandler()->ProcessEvent(event
);