1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/listbox.cpp
4 // Author: Stefan Csomor
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 BEGIN_EVENT_TABLE(wxListBox
, wxControl
)
30 #include "wx/osx/private.h"
32 // ============================================================================
33 // list box control implementation
34 // ============================================================================
36 wxListBox::wxListBox()
40 bool wxListBox::Create(
45 const wxArrayString
& choices
,
47 const wxValidator
& validator
,
48 const wxString
& name
)
50 wxCArrayString
chs(choices
);
53 parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
54 style
, validator
, name
);
57 wxListWidgetImpl
* wxListBox::GetListPeer() const
59 wxListWidgetImpl
* impl
= dynamic_cast<wxListWidgetImpl
*> ( GetPeer() );
63 bool wxListBox::Create(
69 const wxString choices
[],
71 const wxValidator
& validator
,
72 const wxString
& name
)
74 m_blockEvents
= false;
75 m_macIsUserPane
= false;
77 wxASSERT_MSG( !(style
& wxLB_MULTIPLE
) || !(style
& wxLB_EXTENDED
),
78 wxT("only a single listbox selection mode can be specified") );
80 if ( !wxListBoxBase::Create( parent
, id
, pos
, size
, style
& ~(wxHSCROLL
| wxVSCROLL
), validator
, name
) )
84 m_strings
.sorted
= new wxSortedArrayString
;
86 m_strings
.unsorted
= new wxArrayString
;
88 m_peer
= wxWidgetImpl::CreateListBox( this, parent
, id
, pos
, size
, style
, GetExtraStyle() );
90 MacPostControlCreate( pos
, size
);
92 m_textColumn
= GetListPeer()->InsertTextColumn(0,wxEmptyString
);
96 // Needed because it is a wxControlWithItems
97 SetInitialSize( size
);
102 wxListBox::~wxListBox()
104 m_blockEvents
= true;
106 m_blockEvents
= false;
108 // make sure no native events get sent to a object in destruction
112 delete m_strings
.sorted
;
114 delete m_strings
.unsorted
;
116 m_strings
.sorted
= NULL
;
119 void wxListBox::FreeData()
122 m_strings
.sorted
->Clear();
124 m_strings
.unsorted
->Clear();
126 m_itemsClientData
.Clear();
128 GetListPeer()->ListClear();
131 void wxListBox::DoSetFirstItem(int n
)
133 GetListPeer()->ListScrollTo( n
);
136 void wxListBox::EnsureVisible(int n
)
138 GetListPeer()->ListScrollTo( n
);
141 void wxListBox::DoDeleteOneItem(unsigned int n
)
143 wxCHECK_RET( IsValid(n
), wxT("invalid index in wxListBox::Delete") );
145 m_blockEvents
= true;
147 m_strings
.sorted
->RemoveAt(n
);
149 m_strings
.unsorted
->RemoveAt(n
);
151 m_itemsClientData
.RemoveAt(n
);
153 GetListPeer()->ListDelete( n
);
154 m_blockEvents
= false;
156 UpdateOldSelections();
159 void wxListBox::DoClear()
161 m_blockEvents
= true;
163 m_blockEvents
= false;
165 UpdateOldSelections();
168 // ----------------------------------------------------------------------------
170 // ----------------------------------------------------------------------------
172 void wxListBox::DoSetSelection(int n
, bool select
)
174 wxCHECK_RET( n
== wxNOT_FOUND
|| IsValid(n
),
175 wxT("invalid index in wxListBox::SetSelection") );
177 m_blockEvents
= true;
179 if ( n
== wxNOT_FOUND
)
180 GetListPeer()->ListDeselectAll();
182 GetListPeer()->ListSetSelection( n
, select
, HasMultipleSelection() );
184 m_blockEvents
= false;
186 UpdateOldSelections();
189 bool wxListBox::IsSelected(int n
) const
191 wxCHECK_MSG( IsValid(n
), false, wxT("invalid index in wxListBox::Selected") );
193 return GetListPeer()->ListIsSelected( n
);
196 // Return number of selections and an array of selected integers
197 int wxListBox::GetSelections(wxArrayInt
& aSelections
) const
199 return GetListPeer()->ListGetSelections( aSelections
);
202 // Get single selection, for single choice list items
203 int wxListBox::GetSelection() const
205 return GetListPeer()->ListGetSelection();
208 int wxListBox::DoListHitTest(const wxPoint
& inpoint
) const
210 return GetListPeer()->DoListHitTest( inpoint
);
213 // ----------------------------------------------------------------------------
215 // ----------------------------------------------------------------------------
217 void wxListBox::GetValueCallback( unsigned int n
, wxListWidgetColumn
* col
, wxListWidgetCellValue
& value
)
219 if ( col
== m_textColumn
)
220 value
.Set( GetString( n
) );
223 void wxListBox::SetValueCallback( unsigned int WXUNUSED(n
), wxListWidgetColumn
* WXUNUSED(col
) , wxListWidgetCellValue
& WXUNUSED(value
) )
227 wxSize
wxListBox::DoGetBestSize() const
229 int lbWidth
= 100; // some defaults
234 wxClientDC
dc(const_cast<wxListBox
*>(this));
235 dc
.SetFont(GetFont());
237 // Find the widest line
238 for (unsigned int i
= 0; i
< GetCount(); i
++)
240 wxString
str( GetString( i
) );
242 wxCoord width
, height
;
243 dc
.GetTextExtent( str
, &width
, &height
);
245 lbWidth
= wxMax( lbWidth
, wLine
);
248 // Add room for the scrollbar
249 lbWidth
+= wxSystemSettings::GetMetric( wxSYS_VSCROLL_X
);
251 // And just a bit more
254 wxCoord width
, height
;
255 dc
.GetTextExtent( wxT("XX") , &width
, &height
);
259 // don't make the listbox too tall (limit height to around 10 items)
260 // but don't make it too small neither
261 lbHeight
= wxMax( (cy
+ 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 );
264 return wxSize( lbWidth
, lbHeight
);
267 void wxListBox::Refresh(bool eraseBack
, const wxRect
*rect
)
269 wxControl::Refresh( eraseBack
, rect
);
272 // Some custom controls depend on this
273 /* static */ wxVisualAttributes
274 wxListBox::GetClassDefaultAttributes(wxWindowVariant
WXUNUSED(variant
))
276 wxVisualAttributes attr
;
278 attr
.colFg
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT
);
279 attr
.colBg
= wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX
);
280 static wxFont font
= wxFont(wxOSX_SYSTEM_FONT_VIEWS
);
286 // below is all code copied from univ
288 // ----------------------------------------------------------------------------
289 // client data handling
290 // ----------------------------------------------------------------------------
292 void wxListBox::DoSetItemClientData(unsigned int n
, void* clientData
)
294 m_itemsClientData
[n
] = clientData
;
297 void *wxListBox::DoGetItemClientData(unsigned int n
) const
299 return m_itemsClientData
[n
];
302 // ----------------------------------------------------------------------------
304 // ----------------------------------------------------------------------------
306 unsigned int wxListBox::GetCount() const
308 return IsSorted() ? m_strings
.sorted
->size()
309 : m_strings
.unsorted
->size();
312 wxString
wxListBox::GetString(unsigned int n
) const
314 return IsSorted() ? m_strings
.sorted
->Item(n
)
315 : m_strings
.unsorted
->Item(n
);
318 int wxListBox::FindString(const wxString
& s
, bool bCase
) const
320 return IsSorted() ? m_strings
.sorted
->Index(s
, bCase
)
321 : m_strings
.unsorted
->Index(s
, bCase
);
324 // ----------------------------------------------------------------------------
325 // adding/inserting strings
326 // ----------------------------------------------------------------------------
328 void wxListBox::OnItemInserted(unsigned int WXUNUSED(pos
))
333 int wxListBox::DoInsertItems(const wxArrayStringsAdapter
& items
,
336 wxClientDataType type
)
338 int idx
= wxNOT_FOUND
;
339 unsigned int startpos
= pos
;
341 const unsigned int numItems
= items
.GetCount();
342 for ( unsigned int i
= 0; i
< numItems
; ++i
)
344 const wxString
& item
= items
[i
];
345 idx
= IsSorted() ? m_strings
.sorted
->Add(item
)
346 : (m_strings
.unsorted
->Insert(item
, pos
), pos
++);
348 m_itemsClientData
.Insert(NULL
, idx
);
349 AssignNewItemClientData(idx
, clientData
, i
, type
);
351 GetListPeer()->ListInsert(startpos
+i
);
356 GetListPeer()->UpdateLineToEnd(startpos
);
358 // Inserting the items may scroll the listbox down to show the last
359 // selected one but we don't want to do it as it could result in e.g. the
360 // first items of a listbox be hidden immediately after its creation so
361 // show the first selected item instead. Ideal would probably be to
362 // preserve the old selection unchanged, in fact, but I don't know how to
363 // get the first visible item so for now do at least this.
364 SetFirstItem(startpos
);
366 UpdateOldSelections();
371 void wxListBox::SetString(unsigned int n
, const wxString
& s
)
373 wxCHECK_RET( !IsSorted(), wxT("can't set string in sorted listbox") );
376 (*m_strings
.sorted
)[n
] = s
;
378 (*m_strings
.unsorted
)[n
] = s
;
380 GetListPeer()->UpdateLine(n
);
384 // common event handling
387 void wxListBox::HandleLineEvent( unsigned int n
, bool doubleClick
)
389 wxCommandEvent
event( doubleClick
? wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
:
390 wxEVT_COMMAND_LISTBOX_SELECTED
, GetId() );
391 event
.SetEventObject( this );
392 if ( HasClientObjectData() )
393 event
.SetClientObject( GetClientObject(n
) );
394 else if ( HasClientUntypedData() )
395 event
.SetClientData( GetClientData(n
) );
396 event
.SetString( GetString(n
) );
398 event
.SetExtraLong( 1 );
399 HandleWindowEvent(event
);
403 // common list cell value operations
406 void wxListWidgetCellValue::Check( bool check
)
408 Set( check
? 1 : 0 );
411 bool wxListWidgetCellValue::IsChecked() const
413 return GetIntValue() != 0;
418 #endif // wxUSE_LISTBOX