1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/osx/carbon/listbox.cpp 
   4 // Author:      Stefan Csomor 
   7 // RCS-ID:      $Id: listbox.cpp 54820 2008-07-29 20:04:11Z SC $ 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/wxprec.h" 
  16 #include "wx/listbox.h" 
  22     #include "wx/settings.h" 
  23     #include "wx/arrstr.h" 
  24     #include "wx/dcclient.h" 
  27 IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControlWithItems
) 
  29 BEGIN_EVENT_TABLE(wxListBox
, wxControl
) 
  32 #include "wx/osx/private.h" 
  34 // ============================================================================ 
  35 // list box control implementation 
  36 // ============================================================================ 
  38 wxListBox::wxListBox() 
  42 bool wxListBox::Create( 
  47     const wxArrayString
& choices
, 
  49     const wxValidator
& validator
, 
  50     const wxString
& name 
) 
  52     wxCArrayString 
chs(choices
); 
  55         parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), 
  56         style
, validator
, name 
); 
  59 wxListWidgetImpl
* wxListBox::GetListPeer() const 
  61     wxListWidgetImpl
* impl 
=  dynamic_cast<wxListWidgetImpl
*> ( GetPeer() ); 
  65 bool wxListBox::Create( 
  71     const wxString choices
[], 
  73     const wxValidator
& validator
, 
  74     const wxString
& name 
) 
  76     m_blockEvents 
= false; 
  77     m_macIsUserPane 
= false; 
  79     wxASSERT_MSG( !(style 
& wxLB_MULTIPLE
) || !(style 
& wxLB_EXTENDED
), 
  80                   wxT("only a single listbox selection mode can be specified") ); 
  82     if ( !wxListBoxBase::Create( parent
, id
, pos
, size
, style 
& ~(wxHSCROLL 
| wxVSCROLL
), validator
, name 
) ) 
  86         m_strings
.sorted 
= new wxSortedArrayString
; 
  88         m_strings
.unsorted 
= new wxArrayString
; 
  90     m_peer 
= wxWidgetImpl::CreateListBox( this, parent
, id
, pos
, size
, style
, GetExtraStyle() ); 
  92     MacPostControlCreate( pos
, size 
); 
  94     m_textColumn 
= GetListPeer()->InsertTextColumn(0,wxEmptyString
); 
  98    // Needed because it is a wxControlWithItems 
  99     SetInitialSize( size 
); 
 104 wxListBox::~wxListBox() 
 106     m_blockEvents 
= true; 
 108     m_blockEvents 
= false; 
 110     // make sure no native events get sent to a object in destruction 
 115         delete m_strings
.sorted
; 
 117         delete m_strings
.unsorted
; 
 119     m_strings
.sorted 
= NULL
; 
 122 void wxListBox::FreeData() 
 125         m_strings
.sorted
->Clear(); 
 127         m_strings
.unsorted
->Clear(); 
 129     m_itemsClientData
.Clear(); 
 131     GetListPeer()->ListClear(); 
 134 void wxListBox::DoSetFirstItem(int n
) 
 136     GetListPeer()->ListScrollTo( n 
); 
 139 void wxListBox::EnsureVisible(int n
) 
 141     GetListPeer()->ListScrollTo( n 
); 
 144 void wxListBox::DoDeleteOneItem(unsigned int n
) 
 146     wxCHECK_RET( IsValid(n
), wxT("invalid index in wxListBox::Delete") ); 
 148     m_blockEvents 
= true; 
 150         m_strings
.sorted
->RemoveAt(n
); 
 152         m_strings
.unsorted
->RemoveAt(n
); 
 154     m_itemsClientData
.RemoveAt(n
); 
 156     GetListPeer()->ListDelete( n 
); 
 157     m_blockEvents 
= false; 
 159     UpdateOldSelections(); 
 162 void wxListBox::DoClear() 
 164     m_blockEvents 
= true; 
 166     m_blockEvents 
= false; 
 168     UpdateOldSelections(); 
 171 // ---------------------------------------------------------------------------- 
 173 // ---------------------------------------------------------------------------- 
 175 void wxListBox::DoSetSelection(int n
, bool select
) 
 177     wxCHECK_RET( n 
== wxNOT_FOUND 
|| IsValid(n
), 
 178         wxT("invalid index in wxListBox::SetSelection") ); 
 180     m_blockEvents 
= true; 
 182     if ( n 
== wxNOT_FOUND 
) 
 183         GetListPeer()->ListDeselectAll(); 
 185         GetListPeer()->ListSetSelection( n
, select
, HasMultipleSelection() ); 
 187     m_blockEvents 
= false; 
 189     UpdateOldSelections(); 
 192 bool wxListBox::IsSelected(int n
) const 
 194     wxCHECK_MSG( IsValid(n
), false, wxT("invalid index in wxListBox::Selected") ); 
 196     return GetListPeer()->ListIsSelected( n 
); 
 199 // Return number of selections and an array of selected integers 
 200 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const 
 202     return GetListPeer()->ListGetSelections( aSelections 
); 
 205 // Get single selection, for single choice list items 
 206 int wxListBox::GetSelection() const 
 208     return GetListPeer()->ListGetSelection(); 
 211 // ---------------------------------------------------------------------------- 
 213 // ---------------------------------------------------------------------------- 
 215 void wxListBox::GetValueCallback( unsigned int n
, wxListWidgetColumn
* col 
, wxListWidgetCellValue
& value 
) 
 217     if ( col 
== m_textColumn 
) 
 218         value
.Set( GetString( n 
) ); 
 221 void wxListBox::SetValueCallback( unsigned int WXUNUSED(n
), wxListWidgetColumn
* WXUNUSED(col
) , wxListWidgetCellValue
& WXUNUSED(value
) ) 
 225 wxSize 
wxListBox::DoGetBestSize() const 
 227     int lbWidth 
= 100;  // some defaults 
 232         wxClientDC 
dc(const_cast<wxListBox
*>(this)); 
 233         dc
.SetFont(GetFont()); 
 235         // Find the widest line 
 236         for (unsigned int i 
= 0; i 
< GetCount(); i
++) 
 238             wxString 
str( GetString( i 
) ); 
 240             wxCoord width
, height 
; 
 241             dc
.GetTextExtent( str 
, &width
, &height
); 
 243             lbWidth 
= wxMax( lbWidth
, wLine 
); 
 246         // Add room for the scrollbar 
 247         lbWidth 
+= wxSystemSettings::GetMetric( wxSYS_VSCROLL_X 
); 
 249         // And just a bit more 
 252         wxCoord width
, height 
; 
 253         dc
.GetTextExtent( wxT("XX") , &width
, &height
); 
 257         // don't make the listbox too tall (limit height to around 10 items) 
 258         // but don't make it too small neither 
 259         lbHeight 
= wxMax( (cy 
+ 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 ); 
 262     return wxSize( lbWidth
, lbHeight 
); 
 265 void wxListBox::Refresh(bool eraseBack
, const wxRect 
*rect
) 
 267     wxControl::Refresh( eraseBack
, rect 
); 
 270 // Some custom controls depend on this 
 271 /* static */ wxVisualAttributes
 
 272 wxListBox::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 274     wxVisualAttributes attr
; 
 276     attr
.colFg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
 277     attr
.colBg 
= wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX 
); 
 278     attr
.font
.CreateSystemFont(wxOSX_SYSTEM_FONT_VIEWS
); 
 283 // below is all code copied from univ 
 285 // ---------------------------------------------------------------------------- 
 286 // client data handling 
 287 // ---------------------------------------------------------------------------- 
 289 void wxListBox::DoSetItemClientData(unsigned int n
, void* clientData
) 
 291     m_itemsClientData
[n
] = clientData
; 
 294 void *wxListBox::DoGetItemClientData(unsigned int n
) const 
 296     return m_itemsClientData
[n
]; 
 299 // ---------------------------------------------------------------------------- 
 301 // ---------------------------------------------------------------------------- 
 303 unsigned int wxListBox::GetCount() const 
 305     return IsSorted() ? m_strings
.sorted
->size() 
 306                       : m_strings
.unsorted
->size(); 
 309 wxString 
wxListBox::GetString(unsigned int n
) const 
 311     return IsSorted() ? m_strings
.sorted
->Item(n
) 
 312                       : m_strings
.unsorted
->Item(n
); 
 315 int wxListBox::FindString(const wxString
& s
, bool bCase
) const 
 317     return IsSorted() ? m_strings
.sorted
->Index(s
, bCase
) 
 318                       : m_strings
.unsorted
->Index(s
, bCase
); 
 321 // ---------------------------------------------------------------------------- 
 322 // adding/inserting strings 
 323 // ---------------------------------------------------------------------------- 
 325 void wxListBox::OnItemInserted(unsigned int WXUNUSED(pos
)) 
 330 int wxListBox::DoInsertItems(const wxArrayStringsAdapter
& items
, 
 333                              wxClientDataType type
) 
 335     int idx 
= wxNOT_FOUND
; 
 336     unsigned int startpos 
= pos
; 
 338     const unsigned int numItems 
= items
.GetCount(); 
 339     for ( unsigned int i 
= 0; i 
< numItems
; ++i 
) 
 341         const wxString
& item 
= items
[i
]; 
 342         idx 
= IsSorted() ? m_strings
.sorted
->Add(item
) 
 343                          : (m_strings
.unsorted
->Insert(item
, pos
), pos
++); 
 345         m_itemsClientData
.Insert(NULL
, idx
); 
 346         AssignNewItemClientData(idx
, clientData
, i
, type
); 
 348         GetListPeer()->ListInsert(startpos
+i
); 
 353     GetListPeer()->UpdateLineToEnd(startpos
); 
 355     UpdateOldSelections(); 
 360 void wxListBox::SetString(unsigned int n
, const wxString
& s
) 
 362     wxCHECK_RET( !IsSorted(), wxT("can't set string in sorted listbox") ); 
 365         (*m_strings
.sorted
)[n
] = s
; 
 367         (*m_strings
.unsorted
)[n
] = s
; 
 369     GetListPeer()->UpdateLine(n
); 
 373 // common event handling 
 376 void wxListBox::HandleLineEvent( unsigned int n
, bool doubleClick 
) 
 378     wxCommandEvent 
event( doubleClick 
? wxEVT_COMMAND_LISTBOX_DOUBLECLICKED 
: 
 379         wxEVT_COMMAND_LISTBOX_SELECTED
, GetId() ); 
 380     event
.SetEventObject( this ); 
 381     if ( HasClientObjectData() ) 
 382         event
.SetClientObject( GetClientObject(n
) ); 
 383     else if ( HasClientUntypedData() ) 
 384         event
.SetClientData( GetClientData(n
) ); 
 385     event
.SetString( GetString(n
) ); 
 387     event
.SetExtraLong( 1 ); 
 388     HandleWindowEvent(event
); 
 392 // common list cell value operations 
 395 void wxListWidgetCellValue::Check( bool check 
) 
 397     Set( check 
? 1 : 0 ); 
 400 bool wxListWidgetCellValue::IsChecked() const 
 402     return GetIntValue() != 0; 
 407 #endif // wxUSE_LISTBOX