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(), _T("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
);
391 #endif // wxUSE_LISTBOX