1 /////////////////////////////////////////////////////////////////////////////// 
   8 // Copyright:   (c) AUTHOR 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "listbox.h" 
  17 #include "wx/listbox.h" 
  18 #include "wx/settings.h" 
  19 #include "wx/dynarray.h" 
  27 #if !USE_SHARED_LIBRARY 
  28   IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControl
) 
  30 BEGIN_EVENT_TABLE(wxListBox
, wxControl
) 
  31         EVT_SIZE( wxListBox::OnSize 
)  
  35 #include <wx/mac/uma.h> 
  37 extern "C" void MacDrawStringCell(Rect 
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) ; 
  38 const short kwxMacListWithVerticalScrollbar 
= 128 ; 
  40 // ============================================================================ 
  41 // list box control implementation 
  42 // ============================================================================ 
  45 wxListBox::wxListBox() 
  52 bool wxListBox::Create(wxWindow 
*parent
, wxWindowID id
, 
  55                        int n
, const wxString choices
[], 
  57                        const wxValidator
& validator
, 
  60     m_noItems 
= 0 ; // this will be increased by our append command 
  66     MacPreControlCreate( parent 
, id 
,  "" , pos 
, size 
,style
, validator 
, name 
, &bounds 
, title 
) ; 
  73     listDef
.defType 
= kListDefStandardTextType
; 
  75     CreateListBoxControl( parent
->GetMacRootWindow(), &bounds
, false, 0, 1, false, true, 
  76                           14, 14, false, &listDef
, &m_macControl 
); 
  78     GetControlData(m_macControl
, kControlNoPart
, kControlListBoxListHandleTag
, 
  79                    sizeof(ListHandle
), (Ptr
) &m_macList
, &asize
); 
  81     SetControlReference(m_macControl
, (long) this); 
  82     SetControlVisibility(m_macControl
, false, false); 
  85     if ( style 
& wxLB_MULTIPLE 
) 
  87         options 
+= lNoExtend 
; 
  89     else if ( style 
& wxLB_EXTENDED 
) 
  91         options 
+= lExtendDrag 
; 
  97     SetListSelectionFlags(m_macList
, options
); 
 102     m_macControl 
= UMANewControl( parent
->GetMacRootWindow() , &bounds 
, title 
, false , 
 103                                   kwxMacListWithVerticalScrollbar 
, 0 , 0,  
 104                                   kControlListBoxProc 
, (long) this ) ; 
 105     UMAGetControlData( m_macControl 
, kControlNoPart 
, kControlListBoxListHandleTag 
, 
 106                        sizeof( ListHandle 
) , (char*) &m_macList  
, &result 
) ; 
 108     HLock( (Handle
) m_macList 
) ; 
 109     NewExtLDEFInfo( m_macList 
, MacDrawStringCell 
, (long) this ) ; 
 111     (**m_macList
).selFlags 
= 0 ; 
 112     if ( style 
& wxLB_MULTIPLE 
) 
 114         (**m_macList
).selFlags 
+= lNoExtend 
; 
 116     else if ( style 
& wxLB_EXTENDED 
) 
 118         (**m_macList
).selFlags 
+= lExtendDrag 
; 
 122         (**m_macList
).selFlags 
= lOnlyOne 
; 
 125     Point pt 
= (**m_macList
).cellSize 
; 
 127     LCellSize( pt 
, m_macList 
) ; 
 129     LAddColumn( 1 , 0 , m_macList 
) ; 
 131     ControlFontStyleRec         controlstyle 
; 
 132     controlstyle
.flags 
= kControlUseFontMask 
+ kControlUseSizeMask 
; 
 133     //controlstyle.font = kControlFontSmallSystemFont ; 
 134     controlstyle
.font 
= kFontIDMonaco 
; 
 135     controlstyle
.size 
= 9 ; 
 136     //::UMASetControlFontStyle( m_macControl , &controlstyle ) ; 
 139     MacPostControlCreate() ; 
 141     for ( int i 
= 0 ; i 
< n 
; i
++ ) 
 143         Append( choices
[i
] ) ; 
 146     LSetDrawingMode( true , m_macList 
) ; 
 151 wxListBox::~wxListBox() 
 157             DisposeExtLDEFInfo( m_macList 
) ; 
 163 void wxListBox::Free() 
 165 #if wxUSE_OWNER_DRAWN 
 166     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 168         size_t uiCount 
= m_aItems
.Count(); 
 169         while ( uiCount
-- != 0 ) { 
 170             delete m_aItems
[uiCount
]; 
 176 #endif // wxUSE_OWNER_DRAWN 
 177     if ( HasClientObjectData() ) 
 179         for ( size_t n 
= 0; n 
< (size_t)m_noItems
; n
++ ) 
 181             delete GetClientObject(n
); 
 186 void wxListBox::DoSetFirstItem(int N
) 
 191 void wxListBox::Delete(int N
) 
 193     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 194                  wxT("invalid index in wxListBox::Delete") ); 
 196 #if wxUSE_OWNER_DRAWN 
 199 #else // !wxUSE_OWNER_DRAWN 
 200     if ( HasClientObjectData() ) 
 202         delete GetClientObject(N
); 
 204 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 205         m_stringArray
.Remove( N 
) ; 
 206         m_dataArray
.RemoveAt( N 
) ; 
 212 int wxListBox::DoAppend(const wxString
& item
) 
 214         int index 
= m_noItems 
; 
 215         if( wxApp::s_macDefaultEncodingIsPC 
) 
 217                 m_stringArray
.Add( wxMacMakeMacStringFromPC( item 
) ) ; 
 218                 m_dataArray
.Add( NULL 
); 
 221                 m_stringArray
.Add( item 
) ; 
 222                 m_dataArray
.Add( NULL 
); 
 225         DoSetItemClientData( index 
, NULL 
) ; 
 231 void wxListBox::DoSetItems(const wxArrayString
& choices
, void** clientData
) 
 233   MacSetRedraw( false ) ; 
 235   int n 
= choices
.GetCount(); 
 237   for( int i 
= 0 ; i 
< n 
; ++i 
) 
 241 #if wxUSE_OWNER_DRAWN 
 242             wxASSERT_MSG(clientData
[i
] == NULL
, 
 243                          wxT("Can't use client data with owner-drawn listboxes")); 
 244 #else // !wxUSE_OWNER_DRAWN 
 245                 Append( choices
[i
] , clientData
[i
] ) ; 
 249                 Append( choices
[i
] ) ; 
 252 #if wxUSE_OWNER_DRAWN 
 253     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) { 
 254         // first delete old items 
 255         size_t ui 
= m_aItems
.Count(); 
 256         while ( ui
-- != 0 ) { 
 261         // then create new ones 
 262         for ( ui 
= 0; ui 
< (size_t)m_noItems
; ui
++ ) { 
 263             wxOwnerDrawn 
*pNewItem 
= CreateItem(ui
); 
 264             pNewItem
->SetName(choices
[ui
]); 
 265             m_aItems
.Add(pNewItem
); 
 268 #endif // wxUSE_OWNER_DRAWN 
 269   MacSetRedraw( true ) ; 
 272 bool wxListBox::HasMultipleSelection() const 
 274     return (m_windowStyle 
& wxLB_MULTIPLE
) || (m_windowStyle 
& wxLB_EXTENDED
); 
 277 int wxListBox::FindString(const wxString
& st
) const 
 280         if( wxApp::s_macDefaultEncodingIsPC 
) 
 282                 s 
= wxMacMakeMacStringFromPC( st 
) ; 
 287         if ( s
.Right(1) == "*" ) 
 289                 wxString search 
= s
.Left( s
.Length() - 1 ) ; 
 290                 int len 
= search
.Length() ; 
 294                 c2pstrcpy( (StringPtr
) s2 
, search
.c_str() ) ; 
 296                 strcpy( (char *) s2 
, search
.c_str() ) ; 
 297                 c2pstr( (char *) s2 
) ; 
 300         for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 303                 c2pstrcpy( (StringPtr
) s1 
, m_stringArray
[i
].Left( len 
).c_str() ) ; 
 305                 strcpy( (char *) s1 
, m_stringArray
[i
].Left( len 
).c_str() ) ; 
 306                         c2pstr( (char *) s1 
) ; 
 308                 if ( EqualString( s1 
, s2 
, false , false ) ) 
 311             if ( s
.Left(1) = "*" && s
.Length() > 1 ) 
 314                     for ( int i 
= 0 ; i 
< m_noItems 
; ++i 
) 
 316                                 if ( GetString(i
).Lower().Matches(s
) ) 
 327                 c2pstrcpy( (StringPtr
) s2 
, s
.c_str() ) ; 
 329                 strcpy( (char *) s2 
, s
.c_str() ) ; 
 330                 c2pstr( (char *) s2 
) ; 
 333             for ( int i 
= 0 ; i 
< m_noItems 
; ++ i 
) 
 336                 c2pstrcpy( (StringPtr
) s1 
, m_stringArray
[i
].c_str() ) ; 
 338                 strcpy( (char *) s1 
, m_stringArray
[i
].c_str() ) ; 
 339                         c2pstr( (char *) s1 
) ; 
 341                 if ( EqualString( s1 
, s2 
, false , false ) ) 
 348 void wxListBox::Clear() 
 352   m_stringArray
.Empty() ; 
 353   m_dataArray
.Empty() ; 
 357 void wxListBox::SetSelection(int N
, bool select
) 
 359     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 360                  "invalid index in wxListBox::SetSelection" ); 
 361         MacSetSelection( N 
, select 
) ; 
 364 bool wxListBox::IsSelected(int N
) const 
 366     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, FALSE
, 
 367                  "invalid index in wxListBox::Selected" ); 
 369         return MacIsSelected( N 
) ; 
 372 void *wxListBox::DoGetItemClientData(int N
) const 
 374     wxCHECK_MSG( N 
>= 0 && N 
< m_noItems
, NULL
, 
 375                  wxT("invalid index in wxListBox::GetClientData")); 
 377     return (void *)m_dataArray
[N
]; 
 380 wxClientData 
*wxListBox::DoGetItemClientObject(int N
) const 
 382         return (wxClientData 
*) DoGetItemClientData( N 
) ; 
 385 void wxListBox::DoSetItemClientData(int N
, void *Client_data
) 
 387     wxCHECK_RET( N 
>= 0 && N 
< m_noItems
, 
 388                  "invalid index in wxListBox::SetClientData" ); 
 390 #if wxUSE_OWNER_DRAWN 
 391     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 393         // client data must be pointer to wxOwnerDrawn, otherwise we would crash 
 394         // in OnMeasure/OnDraw. 
 395         wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); 
 397 #endif // wxUSE_OWNER_DRAWN 
 398         wxASSERT_MSG( m_dataArray
.GetCount() >= N 
, "invalid client_data array" ) ; 
 400         if ( m_dataArray
.GetCount() > N 
) 
 402         m_dataArray
[N
] = (char*) Client_data 
; 
 406         m_dataArray
.Add( (char*) Client_data 
) ; 
 410 void wxListBox::DoSetItemClientObject(int n
, wxClientData
* clientData
) 
 412     DoSetItemClientData(n
, clientData
); 
 415 // Return number of selections and an array of selected integers 
 416 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const 
 418         return MacGetSelections( aSelections 
) ; 
 421     if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED)) 
 424         for ( int n = 0; n < no_sel; n++ ) 
 429     else  // single-selection listbox 
 438 // Get single selection, for single choice list items 
 439 int wxListBox::GetSelection() const 
 441         return MacGetSelection() ; 
 444 // Find string for position 
 445 wxString 
wxListBox::GetString(int N
) const 
 447         if( wxApp::s_macDefaultEncodingIsPC 
) 
 449                 return          wxMacMakePCStringFromMac( m_stringArray
[N
] ) ; 
 452                 return m_stringArray
[N
]  ; 
 455 void wxListBox::DoInsertItems(const wxArrayString
& items
, int pos
) 
 457     wxCHECK_RET( pos 
>= 0 && pos 
<= m_noItems
, 
 458                  wxT("invalid index in wxListBox::InsertItems") ); 
 460     int nItems 
= items
.GetCount(); 
 462         for ( int i 
= 0 ; i 
< nItems 
; i
++ ) 
 464                 m_stringArray
.Insert( items
[i
] , pos 
+ i 
) ; 
 465                 m_dataArray
.Insert( NULL 
, pos 
+ i 
) ; 
 466                 MacInsert( pos 
+ i 
, items
[i
] ) ; 
 472 void wxListBox::SetString(int N
, const wxString
& s
) 
 475         if( wxApp::s_macDefaultEncodingIsPC 
) 
 477                 str 
= wxMacMakeMacStringFromPC( s 
)  ; 
 481         m_stringArray
[N
] = str 
; 
 485 wxSize 
wxListBox::DoGetBestSize() const 
 487     return wxSize(100, 100); 
 490 int wxListBox::GetCount() const 
 495 void wxListBox::SetupColours() 
 497     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
 498     SetForegroundColour(GetParent()->GetForegroundColour()); 
 501 void wxListBox::Refresh(bool eraseBack
, const wxRect 
*rect
) 
 504     WindowRef rootwindow 
= GetMacRootWindow() ; 
 505     wxWindow
* wxrootwindow 
= wxFindWinFromMacWindow( rootwindow 
) ; 
 506     wxMacDrawingHelper 
focus( wxrootwindow 
); 
 508     UMADrawControl(m_macControl
); 
 511 #if wxUSE_OWNER_DRAWN 
 513 class wxListBoxItem 
: public wxOwnerDrawn
 
 516     wxListBoxItem(const wxString
& str 
= ""); 
 519 wxListBoxItem::wxListBoxItem(const wxString
& str
) : wxOwnerDrawn(str
, FALSE
) 
 521     // no bitmaps/checkmarks 
 525 wxOwnerDrawn 
*wxListBox::CreateItem(size_t n
) 
 527     return new wxListBoxItem(); 
 530 #endif  //USE_OWNER_DRAWN 
 532 // ============================================================================ 
 533 // list box control implementation 
 534 // ============================================================================ 
 536 void MacDrawStringCell(Rect 
*cellRect
, Cell lCell
, ListHandle theList
, long refCon
) 
 539         // typecast our refCon 
 540         list 
= (wxListBox
*)refCon
; 
 542         MoveTo(cellRect
->left 
+ 4 , cellRect
->top 
+ 10 ); 
 543         const wxString text 
= list
->m_stringArray
[lCell
.v
] ; 
 544         ::TextFont( kFontIDMonaco 
) ; 
 547         DrawText(text
, 0 , text
.Length()); 
 551 void wxListBox::MacDelete( int N 
) 
 553     LDelRow( 1 , N 
, m_macList
) ; 
 557 void wxListBox::MacInsert( int n 
, const char * text
)  
 559     Cell cell 
= { 0 , 0 } ; 
 561     LAddRow( 1 , cell
.v 
, m_macList 
) ; 
 562     LSetCell(text
, strlen(text
), cell
, m_macList
); 
 566 void wxListBox::MacAppend( const char * text
)  
 568     Cell cell 
= { 0 , 0 } ; 
 569     cell
.v 
= (**m_macList
).dataBounds
.bottom 
; 
 570     LAddRow( 1 , cell
.v 
, m_macList 
) ; 
 571     LSetCell(text
, strlen(text
), cell
, m_macList
); 
 575 void wxListBox::MacClear()  
 577     LDelRow( (**m_macList
).dataBounds
.bottom 
, 0 , m_macList 
) ; 
 581 void wxListBox::MacSetSelection( int n 
, bool select 
) 
 583         Cell cell 
= { 0 , 0 } ; 
 584         if ( LGetSelect( true , &cell 
, m_macList 
) ) 
 586                 LSetSelect( false , cell 
, m_macList 
) ; 
 590         LSetSelect( select 
, cell 
, m_macList 
) ; 
 591         LAutoScroll( m_macList 
) ; 
 595 bool wxListBox::MacIsSelected( int n 
) const 
 597         Cell cell 
= { 0 , 0 } ; 
 599         return LGetSelect( false , &cell 
, m_macList 
) ; 
 602 void wxListBox::MacDestroy() 
 604 //    DisposeExtLDEFInfo( m_macList ) ; 
 607 int wxListBox::MacGetSelection() const 
 609         Cell cell 
= { 0 , 0 } ; 
 610         if ( LGetSelect( true , &cell 
, m_macList 
) ) 
 616 int wxListBox::MacGetSelections( wxArrayInt
& aSelections 
) const 
 622         Cell cell 
= { 0 , 0 } ; 
 625         while ( LGetSelect( true , &cell 
, m_macList 
) ) 
 627                 aSelections
.Add( cell
.v 
) ; 
 634 void wxListBox::MacSet( int n 
, const char * text 
) 
 636         // our implementation does not store anything in the list 
 637         // so we just have to redraw 
 638         Cell cell 
= { 0 , 0 } ; 
 640         LSetCell(text
, strlen(text
), cell
, m_macList
); 
 644 void wxListBox::MacScrollTo( int n 
) 
 646         // TODO implement scrolling 
 649 void wxListBox::OnSize( const wxSizeEvent 
&event
) 
 654     GetListCellSize(m_macList
, &pt
); 
 656     pt 
= (**m_macList
).cellSize 
; 
 658     pt
.h 
=  m_width 
- 15  ; 
 659     LCellSize( pt 
, m_macList 
) ; 
 662 void wxListBox::MacHandleControlClick( ControlHandle control 
, SInt16 controlpart 
)  
 664         Boolean wasDoubleClick 
= false ; 
 667         UMAGetControlData( m_macControl 
, kControlNoPart 
, kControlListBoxDoubleClickTag 
, sizeof( wasDoubleClick 
) , (char*) &wasDoubleClick  
, &result 
) ; 
 668         if ( !wasDoubleClick 
) 
 678 void wxListBox::MacSetRedraw( bool doDraw 
)  
 680         LSetDrawingMode( doDraw 
, m_macList 
) ; 
 684 void wxListBox::MacDoClick() 
 686         wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_SELECTED
, m_windowId
); 
 687     event
.SetEventObject( this ); 
 689         wxArrayInt aSelections
; 
 690         int n
, count 
= GetSelections(aSelections
); 
 694            if ( HasClientObjectData() ) 
 695               event
.SetClientObject( GetClientObject(n
) ); 
 696           else if ( HasClientUntypedData() ) 
 697               event
.SetClientData( GetClientData(n
) ); 
 698           event
.SetString( GetString(n
) ); 
 705     event
.m_commandInt 
= n
; 
 707     GetEventHandler()->ProcessEvent(event
); 
 710 void wxListBox::MacDoDoubleClick() 
 712     wxCommandEvent 
event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
, m_windowId
); 
 713     event
.SetEventObject( this ); 
 714         GetEventHandler()->ProcessEvent(event
) ;