1 /////////////////////////////////////////////////////////////////////////////// 
   8 // Copyright:   (c) AUTHOR 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "listbox.h" 
  16 #include "wx/listbox.h" 
  17 #include "wx/settings.h" 
  18 #include "wx/dynarray.h" 
  24 #if !USE_SHARED_LIBRARY 
  25   IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControl
) 
  27 BEGIN_EVENT_TABLE(wxListBox
, wxControl
) 
  28         EVT_SIZE( wxListBox::OnSize 
)  
  32 #include <wx/mac/uma.h> 
  34 extern "C" void MacDrawStringCell(Rect 
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) ; 
  35 const short kwxMacListWithVerticalScrollbar 
= 128 ; 
  37 // ============================================================================ 
  38 // list box control implementation 
  39 // ============================================================================ 
  42 wxListBox::wxListBox() 
  49 bool wxListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  52                        int n
, const wxString choices
[], 
  54                        const wxValidator
& validator
, 
  57   m_noItems 
= 0 ; // this will be increased by our append command 
  63         MacPreControlCreate( parent 
, id 
,  "" , pos 
, size 
,style
, validator 
, name 
, &bounds 
, title 
) ; 
  65         m_macControl 
= UMANewControl( parent
->GetMacRootWindow() , &bounds 
, title 
, true , kwxMacListWithVerticalScrollbar 
, 0 , 0,  
  66                 kControlListBoxProc 
, (long) this ) ; 
  69         UMAGetControlData( m_macControl 
, kControlNoPart 
, kControlListBoxListHandleTag 
, sizeof( ListHandle 
) , (char*) &m_macList  
, &result 
) ; 
  71         HLock( (Handle
) m_macList 
) ; 
  72         NewExtLDEFInfo( m_macList 
, MacDrawStringCell 
, (long) this ) ; 
  73         (**m_macList
).selFlags 
= 0 ; 
  74         if ( style 
& wxLB_MULTIPLE 
) 
  76                 (**m_macList
).selFlags 
+= lNoExtend 
; 
  78         else if ( style 
& wxLB_EXTENDED 
) 
  80                 (**m_macList
).selFlags 
+= lExtendDrag 
; 
  84                 (**m_macList
).selFlags 
= lOnlyOne 
; 
  86         Point pt 
= (**m_macList
).cellSize 
; 
  88         LCellSize( pt 
, m_macList 
) ; 
  90         LAddColumn( 1 , 0 , m_macList 
) ; 
  92         MacPostControlCreate() ; 
  94         ControlFontStyleRec             controlstyle 
; 
  95         controlstyle
.flags 
= kControlUseFontMask 
+ kControlUseSizeMask 
; 
  96         //controlstyle.font = kControlFontSmallSystemFont ; 
  97         controlstyle
.font 
= kFontIDMonaco 
; 
  98         controlstyle
.size 
= 9 ; 
  99         ::UMASetControlFontStyle( m_macControl 
, &controlstyle 
) ; 
 101         for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 103                 Append( choices
[i
] ) ; 
 106         LSetDrawingMode( true , m_macList 
) ; 
 111 wxListBox::~wxListBox() 
 116                 DisposeExtLDEFInfo( m_macList 
) ; 
 121 void wxListBox::Free() 
 123 #if wxUSE_OWNER_DRAWN 
 124     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 126         size_t uiCount 
= m_aItems
.Count(); 
 127         while ( uiCount
-- != 0 ) { 
 128             delete m_aItems
[uiCount
]; 
 134 #endif // wxUSE_OWNER_DRAWN 
 135     if ( HasClientObjectData() ) 
 137         for ( size_t n 
= 0; n 
< (size_t)m_noItems
; n
++ ) 
 139             delete GetClientObject(n
); 
 144 void wxListBox::DoSetFirstItem(int N
) 
 149 void wxListBox::Delete(int N
) 
 151     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 152                  wxT("invalid index in wxListBox::Delete") ); 
 154 #if wxUSE_OWNER_DRAWN 
 157 #else // !wxUSE_OWNER_DRAWN 
 158     if ( HasClientObjectData() ) 
 160         delete GetClientObject(N
); 
 162 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 163         m_stringArray
.Remove( N 
) ; 
 164         m_dataArray
.Remove( N 
) ; 
 170 int wxListBox::DoAppend(const wxString
& item
) 
 172         int index 
= m_noItems 
; 
 173         if( wxApp::s_macDefaultEncodingIsPC 
) 
 175                 m_stringArray
.Add( wxMacMakeMacStringFromPC( item 
) ) ; 
 178                 m_stringArray
.Add( item 
) ; 
 185 void wxListBox::DoSetItems(const wxArrayString
& choices
, void** clientData
) 
 187   MacSetRedraw( false ) ; 
 189   int n 
= choices
.GetCount(); 
 191   for( int i 
= 0 ; i 
< n 
; ++i 
) 
 195 #if wxUSE_OWNER_DRAWN 
 196             wxASSERT_MSG(clientData
[i
] == NULL
, 
 197                          wxT("Can't use client data with owner-drawn listboxes")); 
 198 #else // !wxUSE_OWNER_DRAWN 
 199                 Append( choices
[i
] , clientData
[i
] ) ; 
 203                 Append( choices
[i
] ) ; 
 206 #if wxUSE_OWNER_DRAWN 
 207     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) { 
 208         // first delete old items 
 209         size_t ui 
= m_aItems
.Count(); 
 210         while ( ui
-- != 0 ) { 
 215         // then create new ones 
 216         for ( ui 
= 0; ui 
< (size_t)m_noItems
; ui
++ ) { 
 217             wxOwnerDrawn 
*pNewItem 
= CreateItem(ui
); 
 218             pNewItem
->SetName(choices
[ui
]); 
 219             m_aItems
.Add(pNewItem
); 
 222 #endif // wxUSE_OWNER_DRAWN 
 223   MacSetRedraw( true ) ; 
 226 bool wxListBox::HasMultipleSelection() const 
 228     return (m_windowStyle 
& wxLB_MULTIPLE
) || (m_windowStyle 
& wxLB_EXTENDED
); 
 231 int wxListBox::FindString(const wxString
& st
) const 
 234         if( wxApp::s_macDefaultEncodingIsPC 
) 
 236                 s 
= wxMacMakeMacStringFromPC( st 
) ; 
 241         if ( s
.Right(1) == "*" ) 
 243                 wxString search 
= s
.Left( s
.Length() - 1 ) ; 
 244                 int len 
= search
.Length() ; 
 246             strcpy( (char*) s2 
, search
.c_str() ) ; 
 247             c2pstr( (char*) s2 
) ; 
 248         for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 250                 strcpy( (char*) s1 
, m_stringArray
[i
].Left( len 
).c_str() ) ; 
 251                 c2pstr( (char*) s1 
) ; 
 252                 if ( EqualString( s1 
, s2 
, false , false ) ) 
 259             strcpy( (char*) s2 
, s
.c_str() ) ; 
 260             c2pstr( (char*) s2 
) ; 
 261             for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 263                 strcpy( (char*) s1 
, m_stringArray
[i
].c_str() ) ; 
 264                 c2pstr( (char*) s1 
) ; 
 265                 if ( EqualString( s1 
, s2 
, false , false ) ) 
 272 void wxListBox::Clear() 
 276   m_stringArray
.Empty() ; 
 277   m_dataArray
.Empty() ; 
 281 void wxListBox::SetSelection(int N
, bool select
) 
 283     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 284                  "invalid index in wxListBox::SetSelection" ); 
 285         MacSetSelection( N 
, select 
) ; 
 288 bool wxListBox::IsSelected(int N
) const 
 290     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, FALSE
, 
 291                  "invalid index in wxListBox::Selected" ); 
 293         return MacIsSelected( N 
) ; 
 296 void *wxListBox::DoGetItemClientData(int N
) const 
 298     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, NULL
, 
 299                  "invalid index in wxListBox::GetClientData" ); 
 301     return (void *)m_dataArray
[N
]; 
 304 wxClientData 
*wxListBox::DoGetItemClientObject(int N
) const 
 306         return (wxClientData 
*) DoGetItemClientData( N 
) ; 
 309 void wxListBox::DoSetItemClientData(int N
, void *Client_data
) 
 311     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 312                  "invalid index in wxListBox::SetClientData" ); 
 314 #if wxUSE_OWNER_DRAWN 
 315     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 317         // client data must be pointer to wxOwnerDrawn, otherwise we would crash 
 318         // in OnMeasure/OnDraw. 
 319         wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); 
 321 #endif // wxUSE_OWNER_DRAWN 
 322         wxASSERT_MSG( m_dataArray
.GetCount() >= N 
, "invalid client_data array" ) ; 
 324         if ( m_dataArray
.GetCount() > N 
) 
 326         m_dataArray
[N
] = (char*) Client_data 
; 
 330         m_dataArray
.Add( (char*) Client_data 
) ; 
 334 void wxListBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 336     DoSetItemClientData(n
, clientData
); 
 339 // Return number of selections and an array of selected integers 
 340 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const 
 342         return MacGetSelections( aSelections 
) ; 
 345     if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED)) 
 348         for ( int n = 0; n < no_sel; n++ ) 
 353     else  // single-selection listbox 
 362 // Get single selection, for single choice list items 
 363 int wxListBox::GetSelection() const 
 365         return MacGetSelection() ; 
 368 // Find string for position 
 369 wxString 
wxListBox::GetString(int N
) const 
 371         if( wxApp::s_macDefaultEncodingIsPC 
) 
 373                 return          wxMacMakePCStringFromMac( m_stringArray
[N
] ) ; 
 376                 return m_stringArray
[N
]  ; 
 379 void wxListBox::DoInsertItems(const wxArrayString
& items
, int pos
) 
 381     wxCHECK_RET( pos 
>= 0 && pos 
<= m_noItems
, 
 382                  wxT("invalid index in wxListBox::InsertItems") ); 
 384     int nItems 
= items
.GetCount(); 
 386         for ( int i 
= 0 ; i 
< nItems 
; i
++ ) 
 388                 m_stringArray
.Insert( items
[i
] , pos 
+ i 
) ; 
 389                 m_dataArray
.Insert( NULL 
, pos 
+ i 
) ; 
 390                 MacInsert( pos 
+ i 
, items
[i
] ) ; 
 396 void wxListBox::SetString(int N
, const wxString
& s
) 
 399         if( wxApp::s_macDefaultEncodingIsPC 
) 
 401                 str 
= wxMacMakeMacStringFromPC( s 
)  ; 
 405         m_stringArray
[N
] = str 
; 
 409 wxSize 
wxListBox::DoGetBestSize() const 
 411     return wxSize(100, 100); 
 414 int wxListBox::GetCount() const 
 419 void wxListBox::SetupColours() 
 421     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
 422     SetForegroundColour(GetParent()->GetForegroundColour()); 
 425 #if wxUSE_OWNER_DRAWN 
 427 class wxListBoxItem 
: public wxOwnerDrawn
 
 430     wxListBoxItem(const wxString
& str 
= ""); 
 433 wxListBoxItem::wxListBoxItem(const wxString
& str
) : wxOwnerDrawn(str
, FALSE
) 
 435     // no bitmaps/checkmarks 
 439 wxOwnerDrawn 
*wxListBox::CreateItem(size_t n
) 
 441     return new wxListBoxItem(); 
 444 #endif  //USE_OWNER_DRAWN 
 446 // ============================================================================ 
 447 // list box control implementation 
 448 // ============================================================================ 
 450 void MacDrawStringCell(Rect 
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) 
 453         // typecast our refCon 
 454         list 
= (wxListBox
*)refCon
; 
 456         MoveTo(cellRect
->left 
+ 4 , cellRect
->top 
+ 10 ); 
 457         const wxString text 
= list
->m_stringArray
[lCell
.v
] ; 
 458         ::TextFont( kFontIDMonaco 
) ; 
 461         DrawText(text
, 0 , text
.Length()); 
 465 void wxListBox::MacDelete( int N 
) 
 469         Cell cell 
= { 0 , 0 } ; 
 470         UMAGetControlData( m_macControl 
, kControlNoPart 
, kControlListBoxListHandleTag 
, sizeof( ListHandle 
) , (char*) &list  
, &result 
) ; 
 471         LDelRow( 1 , N 
, list 
) ; 
 474 void wxListBox::MacInsert( int n 
, const char * text
)  
 481         LAddRow( 1 , cell
.v 
, m_macList 
) ; 
 484 void wxListBox::MacAppend( const char * text
)  
 486         Cell cell 
= { 0 , 0 } ; 
 487         cell
.v 
= (**m_macList
).dataBounds
.bottom 
; 
 488         LAddRow( 1 , cell
.v 
, m_macList 
) ; 
 491 void wxListBox::MacClear()  
 493         LDelRow( (**m_macList
).dataBounds
.bottom 
, 0 , m_macList 
) ; 
 496 void wxListBox::MacSetSelection( int n 
, bool select 
) 
 498         Cell cell 
= { 0 , 0 } ; 
 499         if ( LGetSelect( TRUE 
, &cell 
, m_macList 
) ) 
 501                 LSetSelect( false , cell 
, m_macList 
) ; 
 505         LSetSelect( select 
, cell 
, m_macList 
) ; 
 506         LAutoScroll( m_macList 
) ; 
 509 bool wxListBox::MacIsSelected( int n 
) const 
 511         Cell cell 
= { 0 , 0 } ; 
 513         return LGetSelect( false , &cell 
, m_macList 
) ; 
 516 void wxListBox::MacDestroy() 
 518 //      DisposeExtLDEFInfo( m_macList ) ; 
 521 int wxListBox::MacGetSelection() const 
 523         Cell cell 
= { 0 , 0 } ; 
 524         if ( LGetSelect( true , &cell 
, m_macList 
) ) 
 530 int wxListBox::MacGetSelections( wxArrayInt
& aSelections 
) const 
 536         Cell cell 
= { 0 , 0 } ; 
 539         while ( LGetSelect( true , &cell 
, m_macList 
) ) 
 541                 aSelections
.Add( cell
.v 
) ; 
 548 void wxListBox::MacSet( int n 
, const char * text 
) 
 550         // our implementation does not store anything in the list 
 551         // so we just have to redraw 
 552         Cell cell 
= { 0 , 0 } ; 
 554         LDraw( cell 
, m_macList 
) ; 
 557 void wxListBox::MacScrollTo( int n 
) 
 559         // TODO implement scrolling 
 562 void wxListBox::OnSize( const wxSizeEvent 
&event
) 
 564         Point pt 
= (**m_macList
).cellSize 
; 
 565         pt
.h 
=  m_width 
- 15  ; 
 566         LCellSize( pt 
, m_macList 
) ; 
 569 void wxListBox::MacHandleControlClick( ControlHandle control 
, SInt16 controlpart 
)  
 571         Boolean wasDoubleClick 
= false ; 
 574         UMAGetControlData( m_macControl 
, kControlNoPart 
, kControlListBoxDoubleClickTag 
, sizeof( wasDoubleClick 
) , (char*) &wasDoubleClick  
, &result 
) ; 
 575         if ( !wasDoubleClick 
) 
 585 void wxListBox::MacSetRedraw( bool doDraw 
)  
 587         LSetDrawingMode( doDraw 
, m_macList 
) ; 
 591 void wxListBox::MacDoClick() 
 593         wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, m_windowId
); 
 594     event
.SetEventObject( this ); 
 596         wxArrayInt aSelections
; 
 597         int n
, count 
= GetSelections(aSelections
); 
 601            if ( HasClientObjectData() ) 
 602               event
.SetClientObject( GetClientObject(n
) ); 
 603           else if ( HasClientUntypedData() ) 
 604               event
.SetClientData( GetClientData(n
) ); 
 605           event
.SetString( GetString(n
) ); 
 612     event
.m_commandInt 
= n
; 
 614     GetEventHandler()->ProcessEvent(event
); 
 617 void wxListBox::MacDoDoubleClick() 
 619     wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
, m_windowId
); 
 620     event
.SetEventObject( this ); 
 621         GetEventHandler()->ProcessEvent(event
) ;