1 /////////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation "listbox.h" 
  16 #include "wx/wxprec.h" 
  21 #include "wx/listbox.h" 
  22 #include "wx/button.h" 
  23 #include "wx/settings.h" 
  24 #include "wx/toplevel.h" 
  25 #include "wx/dynarray.h" 
  30 #if !USE_SHARED_LIBRARY 
  31 IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControl
) 
  33 BEGIN_EVENT_TABLE(wxListBox
, wxControl
) 
  35 //    EVT_SIZE( wxListBox::OnSize ) 
  36     EVT_CHAR( wxListBox::OnChar 
) 
  41 #include "wx/mac/uma.h" 
  43 const short kTextColumnId 
= 1024 ; 
  45 // new databrowserbased version 
  46 // because of the limited insert 
  47 // functionality of DataBrowser, 
  48 // we just introduce id s corresponding 
  51 DataBrowserItemDataUPP gDataBrowserItemDataUPP 
= NULL 
; 
  52 DataBrowserItemNotificationUPP gDataBrowserItemNotificationUPP 
= NULL 
; 
  53 DataBrowserDrawItemUPP gDataBrowserDrawItemUPP 
= NULL 
; 
  55 #if TARGET_API_MAC_OSX 
  56 static pascal void DataBrowserItemNotificationProc(ControlRef browser
, DataBrowserItemID itemID
, 
  57     DataBrowserItemNotification message
, DataBrowserItemDataRef itemData
) 
  59 static pascal  void DataBrowserItemNotificationProc(ControlRef browser
, DataBrowserItemID itemID
, 
  60     DataBrowserItemNotification message
) 
  63     long ref 
= GetControlReference( browser 
) ; 
  66         wxListBox
* list 
= wxDynamicCast( (wxObject
*) ref 
, wxListBox 
) ; 
  68         if (i 
>= 0 && i 
< list
->GetCount() ) 
  70             bool trigger 
= false ; 
  72                 wxEVT_COMMAND_LISTBOX_SELECTED
, list
->GetId() ); 
  75                 case kDataBrowserItemDeselected 
: 
  76                     if ( list
->HasMultipleSelection() ) 
  77                         trigger 
= !list
->MacIsSelectionSuppressed() ; 
  79                 case kDataBrowserItemSelected 
: 
  80                     trigger 
= !list
->MacIsSelectionSuppressed() ; 
  82                 case kDataBrowserItemDoubleClicked 
: 
  83                     event
.SetEventType(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
) ; 
  91                 event
.SetEventObject( list 
); 
  92                 if ( list
->HasClientObjectData() ) 
  93                     event
.SetClientObject( list
->GetClientObject(i
) ); 
  94                 else if ( list
->HasClientUntypedData() ) 
  95                     event
.SetClientData( list
->GetClientData(i
) ); 
  96                 event
.SetString( list
->GetString(i
) ); 
  98                 event
.SetExtraLong( list
->HasMultipleSelection() ? message 
== kDataBrowserItemSelected 
: TRUE 
); 
  99                 wxPostEvent( list
->GetEventHandler() , event 
) ; 
 100                 // direct notification is not always having the listbox GetSelection() having in synch with event 
 101                 // list->GetEventHandler()->ProcessEvent(event) ; 
 107 static pascal OSStatus 
ListBoxGetSetItemData(ControlRef browser
, 
 108     DataBrowserItemID itemID
, DataBrowserPropertyID property
, 
 109     DataBrowserItemDataRef itemData
, Boolean changeValue
) 
 111         OSStatus err 
= errDataBrowserPropertyNotSupported
; 
 120                     long ref 
= GetControlReference( browser 
) ; 
 123                         wxListBox
* list 
= wxDynamicCast( (wxObject
*) ref 
, wxListBox 
) ; 
 125                     if (i 
>= 0 && i 
< list
->GetCount() ) 
 127                                 wxMacCFStringHolder 
cf( list
->GetString(i
) , list
->GetFont().GetEncoding() ) ; 
 128                                 verify_noerr( ::SetDataBrowserItemDataText( itemData 
, cf 
) ) ; 
 144 static pascal void ListBoxDrawProc( ControlRef browser 
, DataBrowserItemID item 
, DataBrowserPropertyID property 
, 
 145     DataBrowserItemState itemState 
, const Rect 
*itemRect 
, SInt16 depth 
, Boolean isColorDevice 
) 
 148     CFStringRef      cfString
; 
 151     cfString  
= CFStringCreateWithFormat( NULL
, NULL
, CFSTR("Row %d"), item 
); 
 153     ThemeDrawingState themeState 
; 
 154     GetThemeDrawingState( &themeState 
) ; 
 156     if ( itemState 
== kDataBrowserItemIsSelected 
)      //  In this sample we handle the "selected" state, all others fall through to our "active" state 
 158         Gestalt( gestaltSystemVersion
, &systemVersion 
); 
 159         if ( (systemVersion 
>= 0x00001030) && (IsControlActive( browser 
) == false) )  //  Panther DB starts using kThemeBrushSecondaryHighlightColor for inactive browser hilighting 
 160             SetThemePen( kThemeBrushSecondaryHighlightColor
, 32, true ); 
 162             SetThemePen( kThemeBrushPrimaryHighlightColor
, 32, true ); 
 164         PaintRect( itemRect 
);                //  First paint the hilite rect, then the text on top 
 165         SetThemeDrawingState( themeState 
, false ) ; 
 167     DrawThemeTextBox( cfString
, kThemeApplicationFont
, kThemeStateActive
, true, itemRect
, teFlushDefault
, NULL 
); 
 168     if ( cfString 
!= NULL 
)   
 169         CFRelease( cfString 
); 
 170     SetThemeDrawingState( themeState 
, true ) ; 
 174 wxListBox::wxListBox() 
 179   m_suppressSelection 
= false ; 
 182 bool wxListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 185                        const wxArrayString
& choices
, 
 187                        const wxValidator
& validator
, 
 188                        const wxString
& name
) 
 190     wxCArrayString 
chs(choices
); 
 192     return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), 
 193                   style
, validator
, name
); 
 196 bool wxListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
 199                        int n
, const wxString choices
[], 
 201                        const wxValidator
& validator
, 
 202                        const wxString
& name
) 
 204     m_macIsUserPane 
= FALSE 
; 
 206     wxASSERT_MSG( !(style 
& wxLB_MULTIPLE
) || !(style 
& wxLB_EXTENDED
), 
 207                   _T("only one of listbox selection modes can be specified") ); 
 209     if ( !wxListBoxBase::Create(parent
, id
, pos
, size
, style 
& ~(wxHSCROLL
|wxVSCROLL
), validator
, name
) ) 
 212     m_noItems 
= 0 ; // this will be increased by our append command 
 215     Rect bounds 
= wxMacGetBoundsForControl( this , pos 
, size 
) ; 
 217     m_peer 
= new wxMacControl(this) ; 
 218     verify_noerr( ::CreateDataBrowserControl( MAC_WXHWND(parent
->MacGetTopLevelWindowRef()), &bounds
, kDataBrowserListView 
, m_peer
->GetControlRefAddr() ) ); 
 220     DataBrowserSelectionFlags  options 
= kDataBrowserDragSelect 
; 
 221     if ( style 
& wxLB_MULTIPLE 
) 
 223         options 
+= kDataBrowserAlwaysExtendSelection 
+ kDataBrowserCmdTogglesSelection  
; 
 225     else if ( style 
& wxLB_EXTENDED 
) 
 231         options 
+= kDataBrowserSelectOnlyOne 
; 
 233     verify_noerr(m_peer
->SetSelectionFlags( options 
) ); 
 235     if ( gDataBrowserItemDataUPP 
== NULL 
) gDataBrowserItemDataUPP 
= NewDataBrowserItemDataUPP(ListBoxGetSetItemData
) ; 
 236     if ( gDataBrowserItemNotificationUPP 
== NULL 
) 
 238         gDataBrowserItemNotificationUPP 
=  
 239 #if TARGET_API_MAC_OSX 
 240                 (DataBrowserItemNotificationUPP
) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc
) ; 
 242                 NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc
) ; 
 245     if ( gDataBrowserDrawItemUPP 
== NULL 
) gDataBrowserDrawItemUPP 
= NewDataBrowserDrawItemUPP(ListBoxDrawProc
) ; 
 247     DataBrowserCallbacks callbacks 
; 
 248     InitializeDataBrowserCallbacks( &callbacks 
, kDataBrowserLatestCallbacks 
) ; 
 250     callbacks
.u
.v1
.itemDataCallback 
= gDataBrowserItemDataUPP
; 
 251         callbacks
.u
.v1
.itemNotificationCallback 
= gDataBrowserItemNotificationUPP
; 
 252     m_peer
->SetCallbacks( &callbacks
); 
 254     DataBrowserCustomCallbacks customCallbacks 
; 
 255     InitializeDataBrowserCustomCallbacks( &customCallbacks 
, kDataBrowserLatestCustomCallbacks 
) ;  
 257     customCallbacks
.u
.v1
.drawItemCallback 
= gDataBrowserDrawItemUPP 
; 
 259     SetDataBrowserCustomCallbacks( m_peer
->GetControlRef() , &customCallbacks 
) ;     
 261     DataBrowserListViewColumnDesc columnDesc 
; 
 262     columnDesc
.headerBtnDesc
.titleOffset 
= 0; 
 263         columnDesc
.headerBtnDesc
.version 
= kDataBrowserListViewLatestHeaderDesc
; 
 265         columnDesc
.headerBtnDesc
.btnFontStyle
.flags     
= 
 266                 kControlUseFontMask 
| kControlUseJustMask
; 
 268         columnDesc
.headerBtnDesc
.btnContentInfo
.contentType 
= kControlNoContent
; 
 269         columnDesc
.headerBtnDesc
.btnFontStyle
.just 
= teFlushDefault
; 
 270         columnDesc
.headerBtnDesc
.minimumWidth 
= 0; 
 271         columnDesc
.headerBtnDesc
.maximumWidth 
= 10000; 
 273         columnDesc
.headerBtnDesc
.btnFontStyle
.font 
= kControlFontViewSystemFont
; 
 274         columnDesc
.headerBtnDesc
.btnFontStyle
.style 
= normal
; 
 275         columnDesc
.headerBtnDesc
.titleString 
= NULL 
; // CFSTR( "" ); 
 277         columnDesc
.propertyDesc
.propertyID 
= kTextColumnId
; 
 278         columnDesc
.propertyDesc
.propertyType 
= kDataBrowserTextType 
; // kDataBrowserCustomType; 
 279         columnDesc
.propertyDesc
.propertyFlags 
= 
 280 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 
 281          kDataBrowserListViewTypeSelectColumn 
| 
 283          kDataBrowserTableViewSelectionColumn 
; 
 285         verify_noerr(m_peer
->AddListViewColumn( &columnDesc
, kDataBrowserListViewAppendColumn
) ) ; 
 286     verify_noerr(m_peer
->AutoSizeListViewColumns() ) ; 
 287     verify_noerr(m_peer
->SetHasScrollBars(false , true ) ) ; 
 288     verify_noerr(m_peer
->SetTableViewHiliteStyle(kDataBrowserTableViewFillHilite  
) ) ; 
 289     verify_noerr(m_peer
->SetListViewHeaderBtnHeight( 0 ) ) ; 
 292     // shouldn't be necessary anymore under 10.2 
 293     m_peer
->SetData( kControlNoPart
, kControlDataBrowserIncludesFrameAndFocusTag
, (Boolean
) false ) ; 
 294     m_peer
->SetNeedsFocusRect( true ) ; 
 297     MacPostControlCreate(pos
,size
) ; 
 299     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 301         Append( choices
[i
] ) ; 
 304     SetBestSize(size
);   // Needed because it is a wxControlWithItems 
 309 wxListBox::~wxListBox() 
 311     m_peer
->SetReference( 0 ) ; 
 313     // avoid access during destruction 
 320 void wxListBox::FreeData() 
 322 #if wxUSE_OWNER_DRAWN 
 323     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 325         size_t uiCount 
= m_aItems
.Count(); 
 326         while ( uiCount
-- != 0 ) { 
 327             delete m_aItems
[uiCount
]; 
 328             m_aItems
[uiCount
] = NULL
; 
 334 #endif // wxUSE_OWNER_DRAWN 
 335     if ( HasClientObjectData() ) 
 337         for ( size_t n 
= 0; n 
< (size_t)m_noItems
; n
++ ) 
 339             delete GetClientObject(n
); 
 344 void  wxListBox::DoSetSize(int x
, int y
, 
 345             int width
, int height
, 
 348     wxControl::DoSetSize( x 
, y 
, width 
, height 
, sizeFlags 
) ; 
 351 void wxListBox::DoSetFirstItem(int N
) 
 356 void wxListBox::Delete(int N
) 
 358     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 359                  wxT("invalid index in wxListBox::Delete") ); 
 361 #if wxUSE_OWNER_DRAWN 
 363     m_aItems
.RemoveAt(N
); 
 364 #else // !wxUSE_OWNER_DRAWN 
 365     if ( HasClientObjectData() ) 
 367         delete GetClientObject(N
); 
 369 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 370     m_stringArray
.RemoveAt( N 
) ; 
 371     m_dataArray
.RemoveAt( N 
) ; 
 377 int wxListBox::DoAppend(const wxString
& item
) 
 379     InvalidateBestSize(); 
 381     int index 
= m_noItems 
; 
 382     m_stringArray
.Add( item 
) ; 
 383     m_dataArray
.Add( NULL 
); 
 385     DoSetItemClientData( index 
, NULL 
) ; 
 391 void wxListBox::DoSetItems(const wxArrayString
& choices
, void** clientData
) 
 394     int n 
= choices
.GetCount(); 
 396     for( int i 
= 0 ; i 
< n 
; ++i 
) 
 400 #if wxUSE_OWNER_DRAWN 
 401             wxASSERT_MSG(clientData
[i
] == NULL
, 
 402                 wxT("Can't use client data with owner-drawn listboxes")); 
 403 #else // !wxUSE_OWNER_DRAWN 
 404             Append( choices
[i
] , clientData
[i
] ) ; 
 408             Append( choices
[i
] ) ; 
 411 #if wxUSE_OWNER_DRAWN 
 412     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) { 
 413         // first delete old items 
 414         size_t ui 
= m_aItems
.Count(); 
 415         while ( ui
-- != 0 ) { 
 421         // then create new ones 
 422         for ( ui 
= 0; ui 
< (size_t)m_noItems
; ui
++ ) { 
 423             wxOwnerDrawn 
*pNewItem 
= CreateItem(ui
); 
 424             pNewItem
->SetName(choices
[ui
]); 
 425             m_aItems
.Add(pNewItem
); 
 428 #endif // wxUSE_OWNER_DRAWN 
 431 int wxListBox::FindString(const wxString
& s
) const 
 434     if ( s
.Right(1) == wxT("*") ) 
 436         wxString search 
= s
.Left( s
.Length() - 1 ) ; 
 437         int len 
= search
.Length() ; 
 439         wxMacStringToPascal( search 
, s2 
) ; 
 441         for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 443                 wxMacStringToPascal( m_stringArray
[i
].Left( len 
) , s1 
) ; 
 445             if ( EqualString( s1 
, s2 
, false , false ) ) 
 448         if ( s
.Left(1) == wxT("*") && s
.Length() > 1 ) 
 452             for ( int i 
= 0 ; i 
< m_noItems 
; ++i 
) 
 454                 if ( GetString(i
).Lower().Matches(st
) ) 
 464         wxMacStringToPascal( s 
, s2 
) ; 
 466         for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 468                 wxMacStringToPascal( m_stringArray
[i
] , s1 
) ; 
 470             if ( EqualString( s1 
, s2 
, false , false ) ) 
 477 void wxListBox::Clear() 
 481     m_stringArray
.Empty() ; 
 482     m_dataArray
.Empty() ; 
 486 void wxListBox::DoSetSelection(int N
, bool select
) 
 488     wxCHECK_RET( N 
== wxNOT_FOUND 
|| (N 
>= 0 && N 
< m_noItems
) , 
 489         wxT("invalid index in wxListBox::SetSelection") ); 
 491     if ( N 
== wxNOT_FOUND 
) 
 494         MacSetSelection( N 
, select 
) ; 
 497 bool wxListBox::IsSelected(int N
) const 
 499     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, FALSE
, 
 500         wxT("invalid index in wxListBox::Selected") ); 
 502     return MacIsSelected( N 
) ; 
 505 void *wxListBox::DoGetItemClientData(int N
) const 
 507     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, NULL
, 
 508         wxT("invalid index in wxListBox::GetClientData")); 
 510     return (void *)m_dataArray
[N
]; 
 513 wxClientData 
*wxListBox::DoGetItemClientObject(int N
) const 
 515     return (wxClientData 
*) DoGetItemClientData( N 
) ; 
 518 void wxListBox::DoSetItemClientData(int N
, void *Client_data
) 
 520     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 521         wxT("invalid index in wxListBox::SetClientData") ); 
 523 #if wxUSE_OWNER_DRAWN 
 524     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 526         // client data must be pointer to wxOwnerDrawn, otherwise we would crash 
 527         // in OnMeasure/OnDraw. 
 528         wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); 
 530 #endif // wxUSE_OWNER_DRAWN 
 531     wxASSERT_MSG( m_dataArray
.GetCount() >= (size_t) N 
, wxT("invalid client_data array") ) ; 
 533     if ( m_dataArray
.GetCount() > (size_t) N 
) 
 535         m_dataArray
[N
] = (char*) Client_data 
; 
 539         m_dataArray
.Add( (char*) Client_data 
) ; 
 543 void wxListBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 545     DoSetItemClientData(n
, clientData
); 
 548 // Return number of selections and an array of selected integers 
 549 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const 
 551     return MacGetSelections( aSelections 
) ; 
 554 // Get single selection, for single choice list items 
 555 int wxListBox::GetSelection() const 
 557     return MacGetSelection() ; 
 560 // Find string for position 
 561 wxString 
wxListBox::GetString(int N
) const 
 563     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, wxEmptyString
, 
 564                  wxT("invalid index in wxListBox::GetString") ); 
 566     return m_stringArray
[N
]  ; 
 569 void wxListBox::DoInsertItems(const wxArrayString
& items
, int pos
) 
 571     wxCHECK_RET( pos 
>= 0 && pos 
<= m_noItems
, 
 572         wxT("invalid index in wxListBox::InsertItems") ); 
 574     InvalidateBestSize(); 
 576     int nItems 
= items
.GetCount(); 
 578     for ( int i 
= 0 ; i 
< nItems 
; i
++ ) 
 580         m_stringArray
.Insert( items
[i
] , pos 
+ i 
) ; 
 581         m_dataArray
.Insert( NULL 
, pos 
+ i 
) ; 
 583         MacInsert( pos 
+ i 
, items
[i
] ) ; 
 587 void wxListBox::SetString(int N
, const wxString
& s
) 
 589     m_stringArray
[N
] = s 
; 
 593 wxSize 
wxListBox::DoGetBestSize() const 
 595     int lbWidth 
= 100;  // some defaults 
 600         wxMacPortStateHelper 
st( UMAGetWindowPort( (WindowRef
) MacGetTopLevelWindowRef() ) ) ; 
 604             ::TextFont( m_font
.MacGetFontNum() ) ; 
 605             ::TextSize( m_font
.MacGetFontSize() ) ; 
 606             ::TextFace( m_font
.MacGetFontStyle() ) ; 
 610             ::TextFont( kFontIDMonaco 
) ; 
 615         // Find the widest line 
 616         for(int i 
= 0; i 
< GetCount(); i
++) { 
 617             wxString 
str(GetString(i
)); 
 621             ::GetThemeTextDimensions( wxMacCFStringHolder( str 
, m_font
.GetEncoding() ) , 
 622                 kThemeCurrentPortFont
, 
 629             wLine 
= ::TextWidth( str
.c_str() , 0 , str
.Length() ) ; 
 631             lbWidth 
= wxMax(lbWidth
, wLine
); 
 634         // Add room for the scrollbar 
 635         lbWidth 
+= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
); 
 637         // And just a bit more 
 639         int cx 
= ::TextWidth( "X" , 0 , 1 ) ; 
 642         // don't make the listbox too tall (limit height to around 10 items) but don't 
 643         // make it too small neither 
 644         lbHeight 
= (cy
+4) * wxMin(wxMax(GetCount(), 3), 10); 
 647     return wxSize(lbWidth
, lbHeight
); 
 650 int wxListBox::GetCount() const 
 655 void wxListBox::Refresh(bool eraseBack
, const wxRect 
*rect
) 
 657     wxControl::Refresh( eraseBack 
, rect 
) ; 
 660 #if wxUSE_OWNER_DRAWN 
 662 class wxListBoxItem 
: public wxOwnerDrawn
 
 665     wxListBoxItem(const wxString
& str 
= ""); 
 668 wxListBoxItem::wxListBoxItem(const wxString
& str
) : wxOwnerDrawn(str
, FALSE
) 
 670     // no bitmaps/checkmarks 
 674 wxOwnerDrawn 
*wxListBox::CreateItem(size_t n
) 
 676     return new wxListBoxItem(); 
 679 #endif  //USE_OWNER_DRAWN 
 682 // Some custom controls depend on this 
 683 /* static */ wxVisualAttributes
 
 684 wxListBox::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 686     wxVisualAttributes attr
; 
 687     attr
.colFg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
); 
 688     attr
.colBg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX
); 
 689     attr
.font  
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
 693 // ============================================================================ 
 694 // list box control implementation 
 695 // ============================================================================ 
 697 void wxListBox::MacDelete( int n 
) 
 699     wxArrayInt selectionBefore 
; 
 700     MacGetSelections( selectionBefore 
) ; 
 702     UInt32 id 
= m_noItems
+1 ; 
 703     verify_noerr( m_peer
->RemoveItems( kDataBrowserNoItem 
, 1 , (UInt32
*) &id 
, kDataBrowserItemNoProperty 
) ) ; 
 704     for ( size_t i 
= 0 ; i 
< selectionBefore
.GetCount() ; ++i 
) 
 706         int current 
= selectionBefore
[i
] ; 
 709             // selection was deleted 
 710             MacSetSelection( current 
, false ) ; 
 712         else if ( current 
> n 
) 
 714             // something behind the deleted item was selected -> move up 
 715             MacSetSelection( current 
- 1 , true ) ; 
 716             MacSetSelection( current 
, false ) ; 
 720     verify_noerr( m_peer
->UpdateItems( kDataBrowserNoItem 
, 1 , (UInt32
*) kDataBrowserNoItem 
, kDataBrowserItemNoProperty 
, kDataBrowserItemNoProperty 
) ) ; 
 723 void wxListBox::MacInsert( int n 
, const wxString
& text
) 
 725     wxArrayInt selectionBefore 
; 
 726     MacGetSelections( selectionBefore 
) ; 
 728     UInt32 id 
= m_noItems 
; // this has already been increased 
 729     verify_noerr( m_peer
->AddItems( kDataBrowserNoItem 
, 1 ,  (UInt32
*) &id 
, kDataBrowserItemNoProperty 
) ) ; 
 731     for ( int i 
= selectionBefore
.GetCount()-1 ; i 
>= 0 ; --i 
) 
 733         int current 
= selectionBefore
[i
] ; 
 736             MacSetSelection( current 
+ 1 , true ) ; 
 737             MacSetSelection( current 
, false ) ; 
 742     verify_noerr( m_peer
->UpdateItems( kDataBrowserNoItem 
, 1 , (UInt32
*) kDataBrowserNoItem 
, kDataBrowserItemNoProperty 
, kDataBrowserItemNoProperty 
) ) ; 
 745 void wxListBox::MacAppend( const wxString
& text
) 
 747     UInt32 id 
= m_noItems 
; // this has already been increased 
 748     verify_noerr( m_peer
->AddItems( kDataBrowserNoItem 
, 1 ,  (UInt32
*) &id 
, kDataBrowserItemNoProperty 
) ) ; 
 749     // no need to deal with selections nor refreshed, as we have appended 
 752 void wxListBox::MacClear() 
 754     verify_noerr( m_peer
->RemoveItems( kDataBrowserNoItem 
, 0 , NULL 
, kDataBrowserItemNoProperty 
) ) ; 
 757 void wxListBox::MacDeselectAll() 
 759     bool former 
= MacSuppressSelection( true ) ; 
 760     verify_noerr(m_peer
->SetSelectedItems( 0 , NULL 
, kDataBrowserItemsRemove 
) ) ; 
 761     MacSuppressSelection( former 
) ; 
 764 void wxListBox::MacSetSelection( int n 
, bool select 
) 
 766     bool former 
= MacSuppressSelection( true ) ; 
 769     if ( m_peer
->IsItemSelected( id 
) != select 
) 
 772             verify_noerr(m_peer
->SetSelectedItems( 1 , & id 
, HasMultipleSelection() ? kDataBrowserItemsAdd 
: kDataBrowserItemsAssign 
) ) ; 
 774             verify_noerr(m_peer
->SetSelectedItems( 1 , & id 
, kDataBrowserItemsRemove 
) ) ; 
 777     MacSuppressSelection( former 
) ; 
 780 bool  wxListBox::MacSuppressSelection( bool suppress 
) 
 782         bool former 
= m_suppressSelection 
; 
 783         m_suppressSelection 
= suppress 
; 
 787 bool wxListBox::MacIsSelected( int n 
) const 
 789     return m_peer
->IsItemSelected( n 
+ 1 ) ; 
 792 int wxListBox::MacGetSelection() const 
 794     for ( int i 
= 0 ; i 
< GetCount() ; ++i 
) 
 796         if ( m_peer
->IsItemSelected( i 
+ 1 ) ) 
 804 int wxListBox::MacGetSelections( wxArrayInt
& aSelections 
) const 
 810     UInt32 first 
, last 
; 
 811     m_peer
->GetSelectionAnchor( &first 
, &last 
) ; 
 812     if ( first 
!= kDataBrowserNoItem 
) 
 814         for ( size_t i 
= first 
; i 
<= last 
; ++i 
) 
 816             if ( m_peer
->IsItemSelected( i 
) ) 
 818                 aSelections
.Add( i 
- 1 ) ; 
 826 void wxListBox::MacSet( int n 
, const wxString
& text 
) 
 828     // as we don't store the strings we only have to issue a redraw 
 830     verify_noerr( m_peer
->UpdateItems( kDataBrowserNoItem 
, 1 , &id 
, kDataBrowserItemNoProperty 
, kDataBrowserItemNoProperty 
) ) ; 
 833 void wxListBox::MacScrollTo( int n 
) 
 836     verify_noerr(  m_peer
->RevealItem( id 
, kTextColumnId 
, kDataBrowserRevealWithoutSelecting 
) ) ; 
 839 #if !TARGET_API_MAC_OSX 
 841 void wxListBox::OnChar(wxKeyEvent
& event
) 
 843     // todo trigger proper events here 
 847     if ( event
.GetKeyCode() == WXK_RETURN 
|| event
.GetKeyCode() == WXK_NUMPAD_ENTER
) 
 849         wxWindow
* parent 
= GetParent() ; 
 850         while( parent  
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL 
) 
 851             parent 
= parent
->GetParent() ; 
 853         if ( parent 
&& parent
->GetDefaultItem() ) 
 855             wxButton 
*def 
= wxDynamicCast(parent
->GetDefaultItem(), 
 857             if ( def 
&& def
->IsEnabled() ) 
 859                 wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() ); 
 860                 event
.SetEventObject(def
); 
 867     /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */ 
 868     else if (event
.GetKeyCode() == WXK_ESCAPE 
|| (event
.GetKeyCode() == '.' && event
.MetaDown() ) ) 
 870         // FIXME: look in ancestors, not just parent. 
 871         wxWindow
* win 
= GetParent()->FindWindow( wxID_CANCEL 
) ; 
 874                 wxCommandEvent 
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
); 
 875                 new_event
.SetEventObject( win 
); 
 876                 win
->GetEventHandler()->ProcessEvent( new_event 
); 
 879     else if ( event
.GetKeyCode() == WXK_TAB 
) 
 881         wxNavigationKeyEvent new_event
; 
 882         new_event
.SetEventObject( this ); 
 883         new_event
.SetDirection( !event
.ShiftDown() ); 
 884         /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */ 
 885         new_event
.SetWindowChange( event
.ControlDown() ); 
 886         new_event
.SetCurrentFocus( this ); 
 887         if ( !GetEventHandler()->ProcessEvent( new_event 
) ) 
 890     else if ( event
.GetKeyCode() == WXK_DOWN 
|| event
.GetKeyCode() == WXK_UP 
) 
 892         // perform the default key handling first 
 893         wxControl::OnKeyDown( event 
) ; 
 895         wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, m_windowId
); 
 896         event
.SetEventObject( this ); 
 898         wxArrayInt aSelections
; 
 899         int n
, count 
= GetSelections(aSelections
); 
 903             if ( HasClientObjectData() ) 
 904                 event
.SetClientObject( GetClientObject(n
) ); 
 905             else if ( HasClientUntypedData() ) 
 906                 event
.SetClientData( GetClientData(n
) ); 
 907             event
.SetString( GetString(n
) ); 
 916         GetEventHandler()->ProcessEvent(event
); 
 920         if ( event
.GetTimestamp() > m_lastTypeIn 
+ 60 ) 
 922             m_typeIn 
= wxEmptyString 
; 
 924         m_lastTypeIn 
= event
.GetTimestamp() ; 
 925         m_typeIn 
+= (char) event
.GetKeyCode() ; 
 926         int line 
= FindString(wxT("*")+m_typeIn
+wxT("*")) ; 
 929             if ( GetSelection() != line 
) 
 932                 wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, m_windowId
); 
 933                 event
.SetEventObject( this ); 
 935                 if ( HasClientObjectData() ) 
 936                     event
.SetClientObject( GetClientObject( line 
) ); 
 937                 else if ( HasClientUntypedData() ) 
 938                     event
.SetClientData( GetClientData(line
) ); 
 939                 event
.SetString( GetString(line
) ); 
 943                 GetEventHandler()->ProcessEvent(event
); 
 949 #endif // !TARGET_API_MAC_OSX