]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/listbox.cpp
listbox rewrite
[wxWidgets.git] / src / mac / carbon / listbox.cpp
CommitLineData
e9576ca5 1///////////////////////////////////////////////////////////////////////////////
11e62fe6 2// Name: src/mac/carbon/listbox.cpp
e9576ca5 3// Purpose: wxListBox
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10///////////////////////////////////////////////////////////////////////////////
11
3d1a4878
SC
12#include "wx/wxprec.h"
13
179e085f
RN
14#if wxUSE_LISTBOX
15
03e11df5 16#include "wx/app.h"
e9576ca5 17#include "wx/listbox.h"
b4726a58 18#include "wx/checklst.h"
dc0ace7c 19#include "wx/button.h"
e9576ca5 20#include "wx/settings.h"
422644a3 21#include "wx/toplevel.h"
e9576ca5
SC
22#include "wx/dynarray.h"
23#include "wx/log.h"
24
519cb848 25#include "wx/utils.h"
519cb848 26
b4726a58
SC
27IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
28
29BEGIN_EVENT_TABLE(wxListBox, wxControl)
30END_EVENT_TABLE()
31
fdd4e6cc
DS
32#include "wx/mac/uma.h"
33
b4726a58
SC
34// common interface for all implementations
35class wxMacListControl : public wxMacControl
36{
cee24bf7 37public:
520b09fc
DS
38 wxMacListControl( wxListBox *peer )
39 : wxMacControl( peer )
b4726a58
SC
40 {
41 }
cee24bf7
DS
42
43 ~wxMacListControl()
b4726a58 44 {
b4726a58 45 }
fdd4e6cc 46
b4726a58 47 virtual void UpdateLine( int n ) = 0;
cee24bf7 48
b4726a58 49 virtual void MacDelete( int n ) = 0;
520b09fc
DS
50 virtual void MacInsert( int n, const wxString& item ) = 0;
51 virtual void MacInsert( int n, const wxArrayString& items ) = 0;
52 virtual void MacAppend( const wxString& item ) = 0;
cee24bf7
DS
53 virtual void MacSet( int n, const wxString& item ) = 0;
54 virtual void MacClear() = 0;
55 virtual void MacDeselectAll() = 0;
56 virtual void MacSetSelection( int n, bool select ) = 0;
57 virtual int MacGetSelection() const = 0;
520b09fc
DS
58 virtual int MacGetSelections( wxArrayInt& aSelections ) const = 0;
59 virtual bool MacIsSelected( int n ) const = 0;
cee24bf7 60 virtual void MacScrollTo( int n ) = 0;
b4726a58 61
cee24bf7 62 wxListBox * GetPeer() const
520b09fc 63 { return (wxListBox*)m_peer; }
b4726a58 64};
fdd4e6cc 65
cee24bf7 66#if 0
b4726a58 67// In case we have to replace data browser ...
cee24bf7 68// custom HIView-based implementation
fdd4e6cc 69
b4726a58
SC
70class wxMacCustomHIViewListControl : public wxMacListControl
71{
cee24bf7
DS
72public:
73 wxMacCustomHIViewListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style );
b4726a58
SC
74 ~wxMacCustomHIViewListControl();
75
76 void MacDelete( int n );
520b09fc
DS
77 void MacInsert( int n, const wxString& item );
78 void MacInsert( int n, const wxArrayString& items );
79 void MacAppend( const wxString& item );
cee24bf7 80 void MacSet( int n, const wxString& item );
b4726a58
SC
81 void MacClear();
82 void MacDeselectAll();
cee24bf7 83 void MacSetSelection( int n, bool select );
b4726a58 84 int MacGetSelection() const;
520b09fc 85 int MacGetSelections( wxArrayInt& aSelections ) const;
b4726a58
SC
86 bool MacIsSelected( int n ) const;
87 void MacScrollTo( int n );
88};
89#endif
519cb848 90
cee24bf7 91// DataBrowser-based implementation
b4726a58
SC
92
93class wxMacDataBrowserListControl : public wxMacListControl
94{
cee24bf7
DS
95public:
96 wxMacDataBrowserListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style );
b4726a58
SC
97 ~wxMacDataBrowserListControl();
98
99 void UpdateLine( int n );
100
101 void MacDelete( int n );
520b09fc
DS
102 void MacInsert( int n, const wxString& item );
103 void MacInsert( int n, const wxArrayString& items );
104 void MacAppend( const wxString& item );
cee24bf7 105 void MacSet( int n, const wxString& item );
b4726a58
SC
106 void MacClear();
107 void MacDeselectAll();
cee24bf7 108 void MacSetSelection( int n, bool select );
b4726a58 109 int MacGetSelection() const;
520b09fc 110 int MacGetSelections( wxArrayInt& aSelections ) const;
b4726a58
SC
111 bool MacIsSelected( int n ) const;
112 void MacScrollTo( int n );
113
114 virtual OSStatus SetSelectionFlags( DataBrowserSelectionFlags );
115 virtual OSStatus AddListViewColumn( DataBrowserListViewColumnDesc *columnDesc,
116 DataBrowserTableViewColumnIndex position );
117 virtual OSStatus AutoSizeListViewColumns();
cee24bf7 118 virtual OSStatus SetHasScrollBars( bool horiz, bool vert );
b4726a58 119 virtual OSStatus SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle );
520b09fc
DS
120 virtual OSStatus SetListViewHeaderBtnHeight( UInt16 height );
121 virtual OSStatus SetCallbacks( const DataBrowserCallbacks *callbacks );
b4726a58 122 virtual OSStatus UpdateItems( DataBrowserItemID container, UInt32 numItems,
cee24bf7 123 const DataBrowserItemID *items,
b4726a58
SC
124 DataBrowserPropertyID preSortProperty,
125 DataBrowserPropertyID propertyID );
126 virtual OSStatus AddItems( DataBrowserItemID container, UInt32 numItems,
cee24bf7 127 const DataBrowserItemID *items,
b4726a58
SC
128 DataBrowserPropertyID preSortProperty );
129 virtual OSStatus RemoveItems( DataBrowserItemID container, UInt32 numItems,
cee24bf7 130 const DataBrowserItemID *items,
b4726a58
SC
131 DataBrowserPropertyID preSortProperty );
132 virtual OSStatus RevealItem( DataBrowserItemID item,
133 DataBrowserPropertyID propertyID,
134 DataBrowserRevealOptions options );
cee24bf7 135 virtual OSStatus GetSelectionAnchor( DataBrowserItemID *first, DataBrowserItemID *last ) const;
b4726a58 136 virtual bool IsItemSelected( DataBrowserItemID item ) const;
520b09fc 137 virtual OSStatus SetSelectedItems( UInt32 numItems,
cee24bf7 138 const DataBrowserItemID *items,
b4726a58
SC
139 DataBrowserSetOption operation );
140
cee24bf7 141private:
b4726a58
SC
142 // as we are getting the same events for human and API selection we have to suppress
143 // events in the latter case
cee24bf7
DS
144 bool MacSuppressSelection( bool suppress );
145 bool MacIsSelectionSuppressed() const { return m_suppressSelection; }
146
147 bool m_suppressSelection;
b4726a58
SC
148
149#if TARGET_API_MAC_OSX
cee24bf7
DS
150 static pascal void DataBrowserItemNotificationProc(
151 ControlRef browser,
152 DataBrowserItemID itemID,
153 DataBrowserItemNotification message,
154 DataBrowserItemDataRef itemData );
b4726a58 155#else
cee24bf7
DS
156 static pascal void DataBrowserItemNotificationProc(
157 ControlRef browser,
158 DataBrowserItemID itemID,
159 DataBrowserItemNotification message );
facd6764 160#endif
b4726a58
SC
161};
162
163// ============================================================================
164// data browser based implementation
165// ============================================================================
e9576ca5 166
b4726a58
SC
167const short kTextColumnId = 1024;
168const short kCheckboxColumnId = 1025;
facd6764 169
520b09fc 170// new DataBrowser-based version
b4726a58
SC
171// because of the limited insert
172// functionality of DataBrowser,
520b09fc 173// we just introduce IDs corresponding
b4726a58 174// to the line number
789ae0cf 175
b4726a58
SC
176DataBrowserItemDataUPP gDataBrowserItemDataUPP = NULL;
177DataBrowserItemNotificationUPP gDataBrowserItemNotificationUPP = NULL;
fdd4e6cc 178
83ce5634 179#if TARGET_API_MAC_OSX
cee24bf7
DS
180pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc(
181 ControlRef browser,
182 DataBrowserItemID itemID,
183 DataBrowserItemNotification message,
520b09fc 184 DataBrowserItemDataRef itemData )
83ce5634 185#else
cee24bf7
DS
186pascal void wxMacDataBrowserListControl::DataBrowserItemNotificationProc(
187 ControlRef browser,
188 DataBrowserItemID itemID,
520b09fc 189 DataBrowserItemNotification message )
83ce5634
SC
190#endif
191{
b4726a58 192 long ref = GetControlReference( browser );
cee24bf7 193 if ( ref != 0 )
83ce5634 194 {
cee24bf7 195 wxListBox *list = wxDynamicCast( (wxObject*)ref, wxListBox );
520b09fc 196 wxMacDataBrowserListControl *peer = (wxMacDataBrowserListControl*) list->GetPeer();
cee24bf7 197
b4726a58 198 int i = itemID - 1;
cee24bf7 199 if (i >= 0 && i < (int)list->GetCount())
8e0f22c0 200 {
b4726a58 201 bool trigger = false;
fdd4e6cc 202 wxCommandEvent event( wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() );
cee24bf7 203 switch (message)
83ce5634 204 {
cee24bf7 205 case kDataBrowserItemDeselected:
8e0f22c0 206 if ( list->HasMultipleSelection() )
b4726a58
SC
207 trigger = !peer->MacIsSelectionSuppressed();
208 break;
fdd4e6cc 209
cee24bf7 210 case kDataBrowserItemSelected:
b4726a58
SC
211 trigger = !peer->MacIsSelectionSuppressed();
212 break;
fdd4e6cc 213
cee24bf7 214 case kDataBrowserItemDoubleClicked:
b4726a58
SC
215 event.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED );
216 trigger = true;
217 break;
fdd4e6cc 218
cee24bf7 219 default:
b4726a58 220 break;
83ce5634 221 }
fdd4e6cc 222
8e0f22c0
SC
223 if ( trigger )
224 {
225 event.SetEventObject( list );
226 if ( list->HasClientObjectData() )
fdd4e6cc 227 event.SetClientObject( list->GetClientObject( i ) );
8e0f22c0 228 else if ( list->HasClientUntypedData() )
fdd4e6cc
DS
229 event.SetClientData( list->GetClientData( i ) );
230 event.SetString( list->GetString( i ) );
b4726a58 231 event.SetInt( i );
fdd4e6cc 232 event.SetExtraLong( list->HasMultipleSelection() ? message == kDataBrowserItemSelected : true );
cee24bf7 233 wxPostEvent( list->GetEventHandler(), event );
520b09fc 234
8e0f22c0 235 // direct notification is not always having the listbox GetSelection() having in synch with event
b4726a58 236 // list->GetEventHandler()->ProcessEvent(event);
c6179a84 237 }
8e0f22c0 238 }
83ce5634
SC
239 }
240}
241
520b09fc
DS
242static pascal OSStatus ListBoxGetSetItemData(
243 ControlRef browser,
244 DataBrowserItemID itemID,
245 DataBrowserPropertyID property,
246 DataBrowserItemDataRef itemData,
247 Boolean changeValue )
facd6764 248{
de1b0aeb
VZ
249 OSStatus err = errDataBrowserPropertyNotSupported;
250
cee24bf7
DS
251 long ref = GetControlReference( browser );
252
520b09fc 253 if ( !changeValue )
de1b0aeb 254 {
520b09fc 255 wxListBox *list = wxDynamicCast( (wxObject*)ref, wxListBox );
b4726a58 256 bool isCheckList = false;
cee24bf7
DS
257 if (list)
258 isCheckList = list->IsKindOf( CLASSINFO(wxCheckListBox) );
259
de1b0aeb
VZ
260 switch (property)
261 {
de1b0aeb 262 case kTextColumnId:
520b09fc 263 if ( ref != 0 )
de1b0aeb 264 {
b4726a58 265 int i = itemID - 1;
520b09fc 266 if (i >= 0 && i < (int)list->GetCount())
de1b0aeb 267 {
cee24bf7 268 wxMacCFStringHolder cf( list->GetString( i ), list->GetFont().GetEncoding() );
520b09fc
DS
269 err = ::SetDataBrowserItemDataText( itemData, cf );
270 verify_noerr( err );
b4726a58 271 err = noErr;
de1b0aeb
VZ
272 }
273 }
fdd4e6cc 274 break;
cee24bf7
DS
275
276 case kCheckboxColumnId:
520b09fc 277 if ( ref != 0 )
cee24bf7 278 {
520b09fc 279 wxCheckListBox *list = wxDynamicCast( (wxObject*)ref, wxCheckListBox );
b4726a58 280 int i = itemID - 1;
cee24bf7
DS
281 if (i >= 0 && (unsigned int) i < list->GetCount())
282 {
520b09fc
DS
283 err = ::SetDataBrowserItemDataButtonValue( itemData, list->IsChecked( i ) ? kThemeButtonOn : kThemeButtonOff );
284 verify_noerr( err );
cee24bf7
DS
285 err = noErr;
286 }
287 }
288 break;
289
290 case kDataBrowserItemIsEditableProperty:
291 if ( isCheckList )
520b09fc 292 err = ::SetDataBrowserItemDataBooleanValue( itemData, true );
cee24bf7 293 break;
c6179a84 294
de1b0aeb 295 default:
fdd4e6cc 296 break;
de1b0aeb
VZ
297 }
298 }
cee24bf7
DS
299 else
300 {
301 switch (property)
302 {
303 case kCheckboxColumnId:
520b09fc 304 if ( ref != 0 )
cee24bf7 305 {
520b09fc 306 wxCheckListBox *list = wxDynamicCast( (wxObject*)ref, wxCheckListBox );
cee24bf7 307 int i = itemID - 1;
520b09fc 308 if (i >= 0 && (unsigned int)i < list->GetCount())
cee24bf7
DS
309 {
310 // we have to change this behind the back, since Check() would be triggering another update round
311 bool newVal = !list->IsChecked( i );
520b09fc
DS
312 err = ::SetDataBrowserItemDataButtonValue( itemData, newVal ? kThemeButtonOn : kThemeButtonOff );
313 verify_noerr( err );
cee24bf7
DS
314 err = noErr;
315 list->m_checks[i] = newVal;
316
520b09fc
DS
317 wxCommandEvent event( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, list->GetId() );
318 event.SetInt( i );
319 event.SetEventObject( list );
320 list->GetEventHandler()->ProcessEvent( event );
cee24bf7
DS
321 }
322 }
323 break;
324
325 default:
326 break;
327 }
328 }
c6179a84 329
de1b0aeb 330 return err;
facd6764 331}
fe3dc505 332
cee24bf7
DS
333wxMacDataBrowserListControl::wxMacDataBrowserListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style)
334 : wxMacListControl( peer )
b4726a58
SC
335{
336 bool isCheckList = peer->IsKindOf( CLASSINFO(wxCheckListBox));
cee24bf7 337
b4726a58 338 m_suppressSelection = false;
cee24bf7
DS
339 Rect bounds = wxMacGetBoundsForControl( peer, pos, size );
340 OSStatus err = ::CreateDataBrowserControl(
341 MAC_WXHWND(peer->MacGetTopLevelWindowRef()),
342 &bounds, kDataBrowserListView, &m_controlRef );
343 verify_noerr( err );
b4726a58
SC
344
345 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
346 if ( style & wxLB_MULTIPLE )
347 {
cee24bf7 348 options |= kDataBrowserAlwaysExtendSelection | kDataBrowserCmdTogglesSelection;
b4726a58
SC
349 }
350 else if ( style & wxLB_EXTENDED )
351 {
352 // default behaviour
353 }
354 else
355 {
cee24bf7 356 options |= kDataBrowserSelectOnlyOne;
b4726a58 357 }
cee24bf7
DS
358 err = SetSelectionFlags( options );
359 verify_noerr( err );
360
361 if ( gDataBrowserItemDataUPP == NULL )
362 gDataBrowserItemDataUPP = NewDataBrowserItemDataUPP(ListBoxGetSetItemData);
b4726a58 363 if ( gDataBrowserItemNotificationUPP == NULL )
cee24bf7
DS
364 {
365 gDataBrowserItemNotificationUPP =
b4726a58 366#if TARGET_API_MAC_OSX
cee24bf7 367 (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc);
b4726a58 368#else
cee24bf7 369 NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc);
b4726a58 370#endif
cee24bf7 371 }
b4726a58
SC
372
373 DataBrowserCallbacks callbacks;
cee24bf7 374 InitializeDataBrowserCallbacks( &callbacks, kDataBrowserLatestCallbacks );
b4726a58
SC
375
376 callbacks.u.v1.itemDataCallback = gDataBrowserItemDataUPP;
cee24bf7
DS
377 callbacks.u.v1.itemNotificationCallback = gDataBrowserItemNotificationUPP;
378 SetCallbacks( &callbacks );
379
b4726a58
SC
380 DataBrowserListViewColumnDesc columnDesc;
381 columnDesc.headerBtnDesc.titleOffset = 0;
cee24bf7 382 columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
b4726a58 383
cee24bf7
DS
384 columnDesc.headerBtnDesc.btnFontStyle.flags =
385 kControlUseFontMask | kControlUseJustMask;
b4726a58 386
cee24bf7
DS
387 columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent;
388 columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault;
389 columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
390 columnDesc.headerBtnDesc.btnFontStyle.style = normal;
391 columnDesc.headerBtnDesc.titleString = NULL;
b4726a58 392
cee24bf7 393 if ( isCheckList )
b4726a58 394 {
cee24bf7
DS
395 columnDesc.headerBtnDesc.minimumWidth = 30;
396 columnDesc.headerBtnDesc.maximumWidth = 30;
397
398 columnDesc.propertyDesc.propertyID = kCheckboxColumnId;
399 columnDesc.propertyDesc.propertyType = kDataBrowserCheckboxType;
400 columnDesc.propertyDesc.propertyFlags =
401 kDataBrowserPropertyIsMutable
402 | kDataBrowserTableViewSelectionColumn
403 | kDataBrowserDefaultPropertyFlags;
404 err = AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn );
405 verify_noerr( err );
b4726a58 406 }
cee24bf7
DS
407
408 columnDesc.headerBtnDesc.minimumWidth = 0;
409 columnDesc.headerBtnDesc.maximumWidth = 10000;
b4726a58 410
cee24bf7
DS
411 columnDesc.propertyDesc.propertyID = kTextColumnId;
412 columnDesc.propertyDesc.propertyType = kDataBrowserTextType;
413 columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn;
b4726a58 414#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
cee24bf7 415 columnDesc.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn;
b4726a58 416#endif
b4726a58 417
cee24bf7
DS
418 verify_noerr( AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn ) );
419 verify_noerr( AutoSizeListViewColumns() );
420 verify_noerr( SetHasScrollBars( false, true ) );
421 verify_noerr( SetTableViewHiliteStyle(kDataBrowserTableViewFillHilite ) );
422 verify_noerr( SetListViewHeaderBtnHeight( 0 ) );
b4726a58
SC
423
424#if 0
425 // shouldn't be necessary anymore under 10.2
cee24bf7 426 m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean)false );
b4726a58
SC
427 m_peer->SetNeedsFocusRect( true );
428#endif
429}
cee24bf7
DS
430
431wxMacDataBrowserListControl::~wxMacDataBrowserListControl()
b4726a58 432{
b4726a58
SC
433}
434
435void wxMacDataBrowserListControl::MacDelete( int n )
436{
437 wxArrayInt selectionBefore;
438 MacGetSelections( selectionBefore );
439
cee24bf7
DS
440 UInt32 id = GetPeer()->GetCount() + 1;
441
442 OSStatus err = RemoveItems( kDataBrowserNoItem, 1, (UInt32*) &id, kDataBrowserItemNoProperty );
443 verify_noerr( err );
444
b4726a58
SC
445 for ( size_t i = 0; i < selectionBefore.GetCount(); ++i )
446 {
447 int current = selectionBefore[i];
448 if ( current == n )
449 {
450 // selection was deleted
cee24bf7 451 MacSetSelection( current, false );
b4726a58
SC
452 }
453 else if ( current > n )
454 {
455 // something behind the deleted item was selected -> move up
cee24bf7
DS
456 MacSetSelection( current - 1, true );
457 MacSetSelection( current, false );
b4726a58
SC
458 }
459 }
cee24bf7 460
b4726a58 461 // refresh all
cee24bf7
DS
462 err = UpdateItems(
463 kDataBrowserNoItem, 1, (UInt32*)kDataBrowserNoItem,
464 kDataBrowserItemNoProperty, kDataBrowserItemNoProperty );
465 verify_noerr( err );
b4726a58
SC
466}
467
cee24bf7 468void wxMacDataBrowserListControl::MacInsert( int n, const wxString& text)
b4726a58
SC
469{
470 wxArrayInt selectionBefore;
471 MacGetSelections( selectionBefore );
472
473 UInt32 id = GetPeer()->GetCount(); // this has already been increased
cee24bf7
DS
474 OSStatus err = AddItems( kDataBrowserNoItem, 1, (UInt32*) &id, kDataBrowserItemNoProperty );
475 verify_noerr( err );
b4726a58 476
cee24bf7 477 for ( int i = selectionBefore.GetCount() - 1; i >= 0; --i )
b4726a58
SC
478 {
479 int current = selectionBefore[i];
480 if ( current >= n )
481 {
cee24bf7
DS
482 MacSetSelection( current + 1, true );
483 MacSetSelection( current, false );
b4726a58
SC
484 }
485 }
486
487 // refresh all
cee24bf7
DS
488 err = UpdateItems(
489 kDataBrowserNoItem, 1, (UInt32*)kDataBrowserNoItem,
490 kDataBrowserItemNoProperty, kDataBrowserItemNoProperty );
491 verify_noerr( err );
b4726a58
SC
492}
493
cee24bf7 494void wxMacDataBrowserListControl::MacInsert( int n, const wxArrayString& items)
b4726a58
SC
495{
496 wxArrayInt selectionBefore;
497 MacGetSelections( selectionBefore );
498 size_t itemsCount = items.GetCount();
499
cee24bf7
DS
500 UInt32 *ids = new UInt32[itemsCount];
501 for ( unsigned int i = 0; i < itemsCount; ++i )
502 ids[i] = GetPeer()->GetCount() - itemsCount + i + 1;
b4726a58 503
cee24bf7
DS
504 OSStatus err = AddItems( kDataBrowserNoItem, itemsCount, ids, kDataBrowserItemNoProperty );
505 verify_noerr( err );
506 delete [] ids;
b4726a58 507
cee24bf7 508 for ( int i = selectionBefore.GetCount() - 1; i >= 0; --i )
b4726a58
SC
509 {
510 int current = selectionBefore[i];
511 if ( current >= n )
512 {
cee24bf7
DS
513 MacSetSelection( current + 1, true );
514 MacSetSelection( current, false );
b4726a58
SC
515 }
516 }
cee24bf7 517
b4726a58 518 // refresh all
cee24bf7
DS
519 err = UpdateItems(
520 kDataBrowserNoItem, 1, (UInt32*)kDataBrowserNoItem,
521 kDataBrowserItemNoProperty, kDataBrowserItemNoProperty );
522 verify_noerr( err );
b4726a58
SC
523}
524
525void wxMacDataBrowserListControl::MacAppend( const wxString& text)
526{
527 UInt32 id = GetPeer()->GetCount(); // this has already been increased
cee24bf7 528 verify_noerr( AddItems( kDataBrowserNoItem, 1, (UInt32*) &id, kDataBrowserItemNoProperty ) );
b4726a58
SC
529 // no need to deal with selections nor refreshed, as we have appended
530}
531
532void wxMacDataBrowserListControl::MacClear()
533{
cee24bf7 534 verify_noerr( RemoveItems( kDataBrowserNoItem, 0, NULL, kDataBrowserItemNoProperty ) );
b4726a58
SC
535}
536
537void wxMacDataBrowserListControl::MacDeselectAll()
538{
539 bool former = MacSuppressSelection( true );
cee24bf7 540 verify_noerr(SetSelectedItems( 0, NULL, kDataBrowserItemsRemove ) );
b4726a58
SC
541 MacSuppressSelection( former );
542}
543
cee24bf7 544void wxMacDataBrowserListControl::MacSetSelection( int n, bool select )
b4726a58 545{
b4726a58 546 UInt32 id = n + 1;
cee24bf7 547 bool former = MacSuppressSelection( true );
b4726a58
SC
548
549 if ( IsItemSelected( id ) != select )
550 {
cee24bf7
DS
551 OSStatus err;
552
b4726a58 553 if ( select )
cee24bf7 554 err = SetSelectedItems( 1, &id, GetPeer()->HasMultipleSelection() ? kDataBrowserItemsAdd : kDataBrowserItemsAssign );
b4726a58 555 else
cee24bf7
DS
556 err = SetSelectedItems( 1, &id, kDataBrowserItemsRemove );
557
558 verify_noerr( err );
b4726a58 559 }
cee24bf7 560
b4726a58
SC
561 MacScrollTo( n );
562 MacSuppressSelection( former );
563}
564
565bool wxMacDataBrowserListControl::MacSuppressSelection( bool suppress )
566{
cee24bf7
DS
567 bool former = m_suppressSelection;
568 m_suppressSelection = suppress;
569
570 return former;
b4726a58
SC
571}
572
573bool wxMacDataBrowserListControl::MacIsSelected( int n ) const
574{
575 return IsItemSelected( n + 1 );
576}
577
578int wxMacDataBrowserListControl::MacGetSelection() const
579{
580 for ( unsigned int i = 0; i < GetPeer()->GetCount(); ++i )
581 {
582 if ( IsItemSelected( i + 1 ) )
583 {
584 return i;
585 }
586 }
cee24bf7 587
b4726a58
SC
588 return -1;
589}
590
591int wxMacDataBrowserListControl::MacGetSelections( wxArrayInt& aSelections ) const
592{
593 int no_sel = 0;
594
595 aSelections.Empty();
596
cee24bf7
DS
597 UInt32 first, last;
598 GetSelectionAnchor( &first, &last );
b4726a58
SC
599 if ( first != kDataBrowserNoItem )
600 {
601 for ( size_t i = first; i <= last; ++i )
602 {
603 if ( IsItemSelected( i ) )
604 {
605 aSelections.Add( i - 1 );
606 no_sel++;
607 }
608 }
609 }
cee24bf7 610
b4726a58
SC
611 return no_sel;
612}
613
cee24bf7 614void wxMacDataBrowserListControl::MacSet( int n, const wxString& text )
b4726a58
SC
615{
616 // as we don't store the strings we only have to issue a redraw
617 UInt32 id = n + 1;
cee24bf7 618 verify_noerr( UpdateItems( kDataBrowserNoItem, 1, &id, kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ) );
b4726a58
SC
619}
620
621void wxMacDataBrowserListControl::MacScrollTo( int n )
622{
623 UInt32 id = n + 1;
cee24bf7 624 verify_noerr( RevealItem( id, kTextColumnId, kDataBrowserRevealWithoutSelecting ) );
b4726a58
SC
625}
626
627void wxMacDataBrowserListControl::UpdateLine( int n )
628{
629 UInt32 id = n + 1;
cee24bf7 630 verify_noerr( UpdateItems(kDataBrowserNoItem, 1, &id, kDataBrowserItemNoProperty, kDataBrowserItemNoProperty ) );
b4726a58
SC
631}
632
633//
634// Databrowser
635//
636
637OSStatus wxMacDataBrowserListControl::SetSelectionFlags( DataBrowserSelectionFlags options )
638{
cee24bf7 639 return SetDataBrowserSelectionFlags( m_controlRef, options );
b4726a58
SC
640}
641
642OSStatus wxMacDataBrowserListControl::AddListViewColumn( DataBrowserListViewColumnDesc *columnDesc,
643 DataBrowserTableViewColumnIndex position )
644{
cee24bf7 645 return AddDataBrowserListViewColumn( m_controlRef, columnDesc, position );
b4726a58
SC
646}
647
648OSStatus wxMacDataBrowserListControl::AutoSizeListViewColumns()
649{
650 return AutoSizeDataBrowserListViewColumns(m_controlRef);
651}
652
cee24bf7 653OSStatus wxMacDataBrowserListControl::SetHasScrollBars( bool horiz, bool vert )
b4726a58 654{
cee24bf7 655 return SetDataBrowserHasScrollBars( m_controlRef, horiz, vert );
b4726a58
SC
656}
657
658OSStatus wxMacDataBrowserListControl::SetTableViewHiliteStyle( DataBrowserTableViewHiliteStyle hiliteStyle )
659{
cee24bf7 660 return SetDataBrowserTableViewHiliteStyle( m_controlRef, hiliteStyle );
b4726a58
SC
661}
662
663OSStatus wxMacDataBrowserListControl::SetListViewHeaderBtnHeight(UInt16 height)
664{
cee24bf7 665 return SetDataBrowserListViewHeaderBtnHeight( m_controlRef, height );
b4726a58
SC
666}
667
cee24bf7 668OSStatus wxMacDataBrowserListControl::SetCallbacks(const DataBrowserCallbacks *callbacks)
b4726a58 669{
cee24bf7 670 return SetDataBrowserCallbacks( m_controlRef, callbacks );
b4726a58
SC
671}
672
cee24bf7
DS
673OSStatus wxMacDataBrowserListControl::UpdateItems(
674 DataBrowserItemID container,
675 UInt32 numItems,
676 const DataBrowserItemID *items,
677 DataBrowserPropertyID preSortProperty,
678 DataBrowserPropertyID propertyID )
b4726a58 679{
cee24bf7 680 return UpdateDataBrowserItems( m_controlRef, container, numItems, items, preSortProperty, propertyID );
b4726a58
SC
681}
682
683bool wxMacDataBrowserListControl::IsItemSelected( DataBrowserItemID item ) const
684{
cee24bf7 685 return IsDataBrowserItemSelected( m_controlRef, item );
b4726a58
SC
686}
687
cee24bf7
DS
688OSStatus wxMacDataBrowserListControl::AddItems(
689 DataBrowserItemID container,
690 UInt32 numItems,
691 const DataBrowserItemID *items,
692 DataBrowserPropertyID preSortProperty )
b4726a58 693{
cee24bf7 694 return AddDataBrowserItems( m_controlRef, container, numItems, items, preSortProperty );
b4726a58
SC
695}
696
cee24bf7
DS
697OSStatus wxMacDataBrowserListControl::RemoveItems(
698 DataBrowserItemID container,
699 UInt32 numItems,
700 const DataBrowserItemID *items,
701 DataBrowserPropertyID preSortProperty )
b4726a58 702{
cee24bf7 703 return RemoveDataBrowserItems( m_controlRef, container, numItems, items, preSortProperty );
b4726a58
SC
704}
705
cee24bf7
DS
706OSStatus wxMacDataBrowserListControl::RevealItem(
707 DataBrowserItemID item,
708 DataBrowserPropertyID propertyID,
709 DataBrowserRevealOptions options )
b4726a58 710{
cee24bf7 711 return RevealDataBrowserItem( m_controlRef, item, propertyID, options );
b4726a58
SC
712}
713
cee24bf7
DS
714OSStatus wxMacDataBrowserListControl::SetSelectedItems(
715 UInt32 numItems,
716 const DataBrowserItemID *items,
717 DataBrowserSetOption operation )
b4726a58 718{
cee24bf7 719 return SetDataBrowserSelectedItems( m_controlRef, numItems, items, operation );
b4726a58
SC
720}
721
cee24bf7 722OSStatus wxMacDataBrowserListControl::GetSelectionAnchor( DataBrowserItemID *first, DataBrowserItemID *last ) const
b4726a58 723{
cee24bf7 724 return GetDataBrowserSelectionAnchor( m_controlRef, first, last );
b4726a58
SC
725}
726
727#if 0
728
729// in case we need that one day
730
731// ============================================================================
cee24bf7 732// HIView owner-draw-based implementation
b4726a58
SC
733// ============================================================================
734
cee24bf7
DS
735static pascal void ListBoxDrawProc(
736 ControlRef browser, DataBrowserItemID item, DataBrowserPropertyID property,
737 DataBrowserItemState itemState, const Rect *itemRect, SInt16 depth, Boolean isColorDevice )
789ae0cf 738{
cee24bf7 739 CFStringRef cfString;
b4726a58 740 ThemeDrawingState themeState;
cee24bf7 741 long systemVersion;
789ae0cf 742
b4726a58 743 GetThemeDrawingState( &themeState );
fdd4e6cc 744 cfString = CFStringCreateWithFormat( NULL, NULL, CFSTR("Row %d"), item );
de1b0aeb 745
fdd4e6cc
DS
746 // In this sample we handle the "selected" state; all others fall through to our "active" state
747 if ( itemState == kDataBrowserItemIsSelected )
789ae0cf 748 {
fdd4e6cc
DS
749 ThemeBrush colorBrushID;
750
cee24bf7
DS
751 // TODO: switch over to wxSystemSettingsNative::GetColour() when kThemeBrushSecondaryHighlightColor
752 // is incorporated Panther DB starts using kThemeBrushSecondaryHighlightColor
753 // for inactive browser highlighting
789ae0cf 754 Gestalt( gestaltSystemVersion, &systemVersion );
fdd4e6cc
DS
755 if ( (systemVersion >= 0x00001030) && !IsControlActive( browser ) )
756 colorBrushID = kThemeBrushSecondaryHighlightColor;
789ae0cf 757 else
fdd4e6cc 758 colorBrushID = kThemeBrushPrimaryHighlightColor;
789ae0cf 759
fdd4e6cc
DS
760 // First paint the hilite rect, then the text on top
761 SetThemePen( colorBrushID, 32, true );
762 PaintRect( itemRect );
cee24bf7 763 SetThemeDrawingState( themeState, false );
789ae0cf 764 }
fdd4e6cc 765
789ae0cf 766 DrawThemeTextBox( cfString, kThemeApplicationFont, kThemeStateActive, true, itemRect, teFlushDefault, NULL );
cee24bf7 767 SetThemeDrawingState( themeState, true );
fdd4e6cc 768
de1b0aeb 769 if ( cfString != NULL )
789ae0cf 770 CFRelease( cfString );
789ae0cf 771}
b4726a58
SC
772#endif
773
b4726a58
SC
774// ============================================================================
775// list box control implementation
776// ============================================================================
fe3dc505 777
fe3dc505
SC
778wxListBox::wxListBox()
779{
520b09fc 780 m_noItems = 0;
fe3dc505
SC
781}
782
520b09fc
DS
783bool wxListBox::Create(
784 wxWindow *parent,
fdd4e6cc
DS
785 wxWindowID id,
786 const wxPoint& pos,
787 const wxSize& size,
788 const wxArrayString& choices,
789 long style,
790 const wxValidator& validator,
520b09fc 791 const wxString& name )
fe3dc505
SC
792{
793 wxCArrayString chs(choices);
794
cee24bf7
DS
795 return Create(
796 parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
520b09fc 797 style, validator, name );
fe3dc505
SC
798}
799
520b09fc
DS
800bool wxListBox::Create(
801 wxWindow *parent,
fdd4e6cc
DS
802 wxWindowID id,
803 const wxPoint& pos,
804 const wxSize& size,
805 int n,
806 const wxString choices[],
807 long style,
808 const wxValidator& validator,
520b09fc 809 const wxString& name )
facd6764 810{
b4726a58 811 m_macIsUserPane = false;
5e6f42cd
SC
812
813 wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
520b09fc 814 wxT("only a single listbox selection mode can be specified") );
c6179a84 815
520b09fc 816 if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
facd6764
SC
817 return false;
818
cee24bf7
DS
819 // this will be increased by our append command
820 m_noItems = 0;
789ae0cf 821
cee24bf7 822 m_peer = CreateMacListControl( pos, size, style );
de1b0aeb 823
cee24bf7 824 MacPostControlCreate( pos, size );
c6179a84 825
cee24bf7 826 InsertItems( n, choices, 0 );
facd6764 827
cee24bf7
DS
828 // Needed because it is a wxControlWithItems
829 SetBestSize( size );
fdd4e6cc 830
cee24bf7 831 return true;
facd6764
SC
832}
833
834wxListBox::~wxListBox()
835{
b4726a58
SC
836 m_peer->SetReference( 0 );
837 FreeData();
838}
fdd4e6cc 839
cee24bf7 840wxMacListControl * wxListBox::CreateMacListControl(const wxPoint& pos, const wxSize& size, long style)
b4726a58 841{
cee24bf7 842 return new wxMacDataBrowserListControl( this, pos, size, style );
facd6764
SC
843}
844
845void wxListBox::FreeData()
846{
b4726a58
SC
847#if wxUSE_OWNER_DRAWN
848 if ( m_windowStyle & wxLB_OWNERDRAW )
849 {
850 size_t uiCount = m_aItems.Count();
cee24bf7
DS
851 while ( uiCount != 0 )
852 {
853 uiCount--;
b4726a58
SC
854 delete m_aItems[uiCount];
855 m_aItems[uiCount] = NULL;
856 }
857
858 m_aItems.Clear();
859 }
860 else
cee24bf7 861#endif
facd6764
SC
862 if ( HasClientObjectData() )
863 {
aa61d352 864 for ( unsigned int n = 0; n < m_noItems; n++ )
facd6764 865 {
fdd4e6cc 866 delete GetClientObject( n );
facd6764
SC
867 }
868 }
869}
870
871void wxListBox::DoSetSize(int x, int y,
872 int width, int height,
873 int sizeFlags )
874{
cee24bf7 875 wxControl::DoSetSize( x, y, width, height, sizeFlags );
facd6764
SC
876}
877
fdd4e6cc 878void wxListBox::DoSetFirstItem(int n)
facd6764 879{
b4726a58 880 GetPeer()->MacScrollTo( n );
facd6764
SC
881}
882
aa61d352 883void wxListBox::Delete(unsigned int n)
facd6764 884{
cee24bf7 885 wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::Delete") );
facd6764 886
b4726a58
SC
887#if wxUSE_OWNER_DRAWN
888 delete m_aItems[n];
889 m_aItems.RemoveAt(n);
cee24bf7 890#else
facd6764 891 if ( HasClientObjectData() )
b4726a58
SC
892 {
893 delete GetClientObject(n);
894 }
cee24bf7
DS
895#endif
896
b4726a58
SC
897 m_stringArray.RemoveAt( n );
898 m_dataArray.RemoveAt( n );
cee24bf7 899 m_noItems--;
facd6764 900
b4726a58 901 GetPeer()->MacDelete( n );
facd6764
SC
902}
903
904int wxListBox::DoAppend(const wxString& item)
905{
9f884528
RD
906 InvalidateBestSize();
907
b4726a58
SC
908 unsigned int index = m_noItems;
909 m_stringArray.Add( item );
facd6764 910 m_dataArray.Add( NULL );
fdd4e6cc 911 m_noItems++;
cee24bf7 912 DoSetItemClientData( index, NULL );
b4726a58 913 GetPeer()->MacAppend( item );
facd6764 914
b4726a58 915 return index;
facd6764
SC
916}
917
918void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
919{
b4726a58 920 Clear();
aa61d352 921 unsigned int n = choices.GetCount();
c6179a84 922
b4726a58 923 for ( size_t i = 0; i < n; ++i )
facd6764
SC
924 {
925 if ( clientData )
b4726a58
SC
926 {
927#if wxUSE_OWNER_DRAWN
928 wxASSERT_MSG(clientData[i] == NULL,
520b09fc 929 wxT("Cannot use client data with owner-drawn listboxes"));
cee24bf7
DS
930#else
931 Append( choices[i], clientData[i] );
b4726a58
SC
932#endif
933 }
facd6764 934 else
b4726a58 935 Append( choices[i] );
facd6764 936 }
b4726a58
SC
937
938#if wxUSE_OWNER_DRAWN
cee24bf7
DS
939 if ( m_windowStyle & wxLB_OWNERDRAW )
940 {
b4726a58
SC
941 // first delete old items
942 size_t ui = m_aItems.Count();
cee24bf7
DS
943 while ( ui != 0 )
944 {
945 ui--;
b4726a58
SC
946 delete m_aItems[ui];
947 m_aItems[ui] = NULL;
948 }
cee24bf7 949
b4726a58
SC
950 m_aItems.Empty();
951
952 // then create new ones
cee24bf7
DS
953 for ( ui = 0; ui < (size_t)m_noItems; ui++ )
954 {
b4726a58
SC
955 wxOwnerDrawn *pNewItem = CreateItem(ui);
956 pNewItem->SetName(choices[ui]);
957 m_aItems.Add(pNewItem);
958 }
959 }
cee24bf7 960#endif
facd6764
SC
961}
962
11e62fe6 963int wxListBox::FindString(const wxString& s, bool bCase) const
facd6764 964{
b4726a58 965 for ( size_t i = 0; i < m_noItems; ++ i )
facd6764 966 {
520b09fc 967 if (s.IsSameAs( GetString( i ), bCase) )
b4726a58 968 return (int)i;
facd6764 969 }
fdd4e6cc 970
11e62fe6 971 return wxNOT_FOUND;
facd6764
SC
972}
973
974void wxListBox::Clear()
975{
976 FreeData();
977 m_noItems = 0;
b4726a58
SC
978 m_stringArray.Empty();
979 m_dataArray.Empty();
980 GetPeer()->MacClear();
facd6764
SC
981}
982
fdd4e6cc 983void wxListBox::DoSetSelection(int n, bool select)
facd6764 984{
cee24bf7 985 wxCHECK_RET( n == wxNOT_FOUND || IsValid(n),
facd6764 986 wxT("invalid index in wxListBox::SetSelection") );
c6179a84 987
fdd4e6cc 988 if ( n == wxNOT_FOUND )
b4726a58 989 GetPeer()->MacDeselectAll();
fe3dc505 990 else
cee24bf7 991 GetPeer()->MacSetSelection( n, select );
facd6764
SC
992}
993
fdd4e6cc 994bool wxListBox::IsSelected(int n) const
facd6764 995{
cee24bf7 996 wxCHECK_MSG( IsValid(n), false, wxT("invalid index in wxListBox::Selected") );
c6179a84 997
b4726a58 998 return GetPeer()->MacIsSelected( n );
facd6764
SC
999}
1000
aa61d352 1001void *wxListBox::DoGetItemClientData(unsigned int n) const
facd6764 1002{
8228b893
WS
1003 wxCHECK_MSG( IsValid(n), NULL, wxT("invalid index in wxListBox::GetClientData"));
1004
520b09fc 1005 wxASSERT_MSG( m_dataArray.GetCount() >= (unsigned int)n, wxT("invalid client_data array") );
c6179a84 1006
520b09fc 1007 return (void*)m_dataArray[n];
facd6764
SC
1008}
1009
aa61d352 1010wxClientData *wxListBox::DoGetItemClientObject(unsigned int n) const
facd6764 1011{
520b09fc 1012 return (wxClientData*)DoGetItemClientData( n );
facd6764
SC
1013}
1014
aa61d352 1015void wxListBox::DoSetItemClientData(unsigned int n, void *clientData)
facd6764 1016{
8228b893 1017 wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::SetClientData") );
c6179a84 1018
b4726a58
SC
1019#if wxUSE_OWNER_DRAWN
1020 if ( m_windowStyle & wxLB_OWNERDRAW )
1021 {
1022 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
1023 // in OnMeasure/OnDraw.
520b09fc 1024 wxFAIL_MSG(wxT("Cannot use client data with owner-drawn listboxes"));
b4726a58 1025 }
cee24bf7
DS
1026#endif
1027
520b09fc 1028 wxASSERT_MSG( m_dataArray.GetCount() >= (unsigned int)n, wxT("invalid client_data array") );
c6179a84 1029
520b09fc 1030 if ( m_dataArray.GetCount() > (unsigned int)n )
b4726a58 1031 m_dataArray[n] = (char*)clientData;
facd6764 1032 else
b4726a58 1033 m_dataArray.Add( (char*)clientData );
facd6764
SC
1034}
1035
aa61d352 1036void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
facd6764
SC
1037{
1038 DoSetItemClientData(n, clientData);
1039}
1040
1041// Return number of selections and an array of selected integers
1042int wxListBox::GetSelections(wxArrayInt& aSelections) const
1043{
b4726a58 1044 return GetPeer()->MacGetSelections( aSelections );
facd6764
SC
1045}
1046
1047// Get single selection, for single choice list items
1048int wxListBox::GetSelection() const
1049{
b4726a58 1050 return GetPeer()->MacGetSelection();
facd6764
SC
1051}
1052
1053// Find string for position
aa61d352 1054wxString wxListBox::GetString(unsigned int n) const
facd6764 1055{
cee24bf7 1056 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxListBox::GetString") );
55ae2833 1057
cee24bf7 1058 return m_stringArray[n];
facd6764
SC
1059}
1060
aa61d352 1061void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
facd6764 1062{
cee24bf7 1063 wxCHECK_RET( IsValidInsert(pos), wxT("invalid index in wxListBox::InsertItems") );
c6179a84 1064
9f884528
RD
1065 InvalidateBestSize();
1066
aa61d352 1067 unsigned int nItems = items.GetCount();
c6179a84 1068
b4726a58 1069 for ( unsigned int i = 0; i < nItems; i++ )
cee24bf7
DS
1070 m_stringArray.Insert( items[i], pos + i );
1071 m_dataArray.Insert( NULL, pos, nItems );
b4726a58 1072 m_noItems += nItems;
cee24bf7 1073 GetPeer()->MacInsert( pos, items );
facd6764
SC
1074}
1075
aa61d352 1076void wxListBox::SetString(unsigned int n, const wxString& s)
facd6764 1077{
b4726a58 1078 m_stringArray[n] = s;
cee24bf7 1079 GetPeer()->MacSet( n, s );
facd6764
SC
1080}
1081
1082wxSize wxListBox::DoGetBestSize() const
1083{
1084 int lbWidth = 100; // some defaults
1085 int lbHeight = 110;
1086 int wLine;
1087
1088 {
b4726a58 1089 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef)MacGetTopLevelWindowRef() ) );
c6179a84 1090
fdd4e6cc 1091 // TODO: clean this up
facd6764
SC
1092 if ( m_font.Ok() )
1093 {
b4726a58
SC
1094 ::TextFont( m_font.MacGetFontNum() );
1095 ::TextSize( m_font.MacGetFontSize() );
1096 ::TextFace( m_font.MacGetFontStyle() );
facd6764
SC
1097 }
1098 else
1099 {
b4726a58 1100 ::TextFont( kFontIDMonaco );
520b09fc 1101 ::TextSize( 9 );
b4726a58 1102 ::TextFace( 0 );
facd6764 1103 }
c6179a84 1104
facd6764 1105 // Find the widest line
aa61d352 1106 for (unsigned int i = 0; i < GetCount(); i++)
fdd4e6cc 1107 {
520b09fc 1108 wxString str( GetString( i ) );
fdd4e6cc
DS
1109
1110#if wxUSE_UNICODE
b4726a58
SC
1111 Point bounds = {0, 0};
1112 SInt16 baseline;
fdd4e6cc
DS
1113
1114 // NB: what if m_font.Ok() == false ???
1115 ::GetThemeTextDimensions(
cee24bf7 1116 wxMacCFStringHolder( str, m_font.GetEncoding() ),
facd6764
SC
1117 kThemeCurrentPortFont,
1118 kThemeStateActive,
1119 false,
1120 &bounds,
1121 &baseline );
b4726a58 1122 wLine = bounds.h;
fdd4e6cc 1123#else
cee24bf7 1124 wLine = ::TextWidth( str.c_str(), 0, str.length() );
fdd4e6cc
DS
1125#endif
1126
1127 lbWidth = wxMax( lbWidth, wLine );
facd6764 1128 }
c6179a84 1129
facd6764 1130 // Add room for the scrollbar
520b09fc 1131 lbWidth += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );
c6179a84 1132
facd6764 1133 // And just a bit more
b4726a58 1134 int cy = 12;
cee24bf7 1135 int cx = ::TextWidth( "X", 0, 1 );
b4726a58 1136 lbWidth += cx;
c6179a84 1137
fdd4e6cc
DS
1138 // don't make the listbox too tall (limit height to around 10 items)
1139 // but don't make it too small neither
9761ab43 1140 lbHeight = wxMax( (cy + 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 );
facd6764
SC
1141 }
1142
fdd4e6cc 1143 return wxSize( lbWidth, lbHeight );
facd6764
SC
1144}
1145
aa61d352 1146unsigned int wxListBox::GetCount() const
facd6764
SC
1147{
1148 return m_noItems;
1149}
1150
1151void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
1152{
cee24bf7 1153 wxControl::Refresh( eraseBack, rect );
facd6764
SC
1154}
1155
cee24bf7 1156void wxListBox::MacUpdateLine(int n)
b6a20a20 1157{
b4726a58 1158 GetPeer()->UpdateLine(n);
b6a20a20
RD
1159}
1160
b4726a58 1161#if wxUSE_OWNER_DRAWN
facd6764 1162
b4726a58 1163class wxListBoxItem : public wxOwnerDrawn
facd6764 1164{
b4726a58
SC
1165public:
1166 wxListBoxItem(const wxString& str = "");
1167};
fdd4e6cc 1168
cee24bf7
DS
1169wxListBoxItem::wxListBoxItem(const wxString& str)
1170 : wxOwnerDrawn(str, false)
facd6764 1171{
b4726a58 1172 // no bitmaps/checkmarks
520b09fc 1173 SetMarginWidth( 0 );
facd6764
SC
1174}
1175
b4726a58 1176wxOwnerDrawn *wxListBox::CreateItem(size_t n)
facd6764 1177{
b4726a58 1178 return new wxListBoxItem();
facd6764
SC
1179}
1180
cee24bf7 1181#endif // USE_OWNER_DRAWN
fdd4e6cc 1182
facd6764 1183
b4726a58
SC
1184// Some custom controls depend on this
1185/* static */ wxVisualAttributes
1186wxListBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
facd6764 1187{
b4726a58 1188 wxVisualAttributes attr;
519cb848 1189
b4726a58
SC
1190 attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
1191 attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
1192 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
e42e45a9 1193
b4726a58 1194 return attr;
facd6764
SC
1195}
1196
443e2f09
VZ
1197int wxListBox::DoListHitTest(const wxPoint& inpoint) const
1198{
cee24bf7 1199 OSStatus err;
443e2f09
VZ
1200
1201 // There are few reasons why this is complicated:
cee24bf7 1202 // 1) There is no native HitTest function for Mac
443e2f09
VZ
1203 // 2) GetDataBrowserItemPartBounds only works on visible items
1204 // 3) We can't do it through GetDataBrowserTableView[Item]RowHeight
1205 // because what it returns is basically inaccurate in the context
1206 // of the coordinates we want here, but we use this as a guess
1207 // for where the first visible item lies
1208
1209 wxPoint point = inpoint;
cee24bf7 1210
443e2f09
VZ
1211 // interestingly enough 10.2 (and below?) have GetDataBrowserItemPartBounds
1212 // giving root window coordinates but 10.3 and above give client coordinates
1213 // so we only compare using root window coordinates on 10.3 and up
1214 if ( UMAGetSystemVersion() < 0x1030 )
1215 MacClientToRootWindow(&point.x, &point.y);
1216
cee24bf7 1217 // get column property ID (req. for call to itempartbounds)
c00fed0e 1218 DataBrowserTableViewColumnID colId = 0;
443e2f09
VZ
1219 err = GetDataBrowserTableViewColumnProperty(m_peer->GetControlRef(), 0, &colId);
1220 wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty"));
1221
1222 // OK, first we need to find the first visible item we have -
1223 // this will be the "low" for our binary search. There is no real
1224 // easy way around this, as we will need to do a SLOW linear search
1225 // until we find a visible item, but we can do a cheap calculation
1226 // via the row height to speed things up a bit
1227 UInt32 scrollx, scrolly;
1228 err = GetDataBrowserScrollPosition(m_peer->GetControlRef(), &scrollx, &scrolly);
1229 wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserScrollPosition"));
1230
1231 UInt16 height;
1232 err = GetDataBrowserTableViewRowHeight(m_peer->GetControlRef(), &height);
1233 wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewRowHeight"));
1234
1235 // these indices are 0-based, as usual, so we need to add 1 to them when
1236 // passing them to data browser functions which use 1-based indices
1237 int low = scrolly / height,
1238 high = GetCount() - 1;
1239
443e2f09
VZ
1240 // search for the first visible item (note that the scroll guess above
1241 // is the low bounds of where the item might lie so we only use that as a
1242 // starting point - we should reach it within 1 or 2 iterations of the loop)
1243 while ( low <= high )
1244 {
1245 Rect bounds;
cee24bf7
DS
1246 err = GetDataBrowserItemPartBounds(
1247 m_peer->GetControlRef(), low + 1, colId,
1248 kDataBrowserPropertyEnclosingPart,
1249 &bounds); // note +1 to translate to Mac ID
443e2f09
VZ
1250 if ( err == noErr )
1251 break;
1252
1253 // errDataBrowserItemNotFound is expected as it simply means that the
1254 // item is not currently visible -- but other errors are not
1255 wxCHECK_MSG( err == errDataBrowserItemNotFound, wxNOT_FOUND,
1256 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
1257
1258 low++;
1259 }
c00fed0e 1260
443e2f09
VZ
1261 // NOW do a binary search for where the item lies, searching low again if
1262 // we hit an item that isn't visible
1263 while ( low <= high )
c00fed0e 1264 {
443e2f09
VZ
1265 int mid = (low + high) / 2;
1266
c00fed0e 1267 Rect bounds;
cee24bf7
DS
1268 err = GetDataBrowserItemPartBounds(
1269 m_peer->GetControlRef(), mid + 1, colId,
1270 kDataBrowserPropertyEnclosingPart,
1271 &bounds); //note +1 to trans to mac id
443e2f09
VZ
1272 wxCHECK_MSG( err == noErr || err == errDataBrowserItemNotFound,
1273 wxNOT_FOUND,
1274 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
1275
1276 if ( err == errDataBrowserItemNotFound )
c00fed0e 1277 {
443e2f09 1278 // item not visible, attempt to find a visible one
cee24bf7
DS
1279 // search lower
1280 high = mid - 1;
443e2f09
VZ
1281 }
1282 else // visible item, do actual hitttest
1283 {
1284 // if point is within the bounds, return this item (since we assume
1285 // all x coords of items are equal we only test the x coord in
1286 // equality)
cee24bf7 1287 if ((point.x >= bounds.left && point.x <= bounds.right) &&
443e2f09
VZ
1288 (point.y >= bounds.top && point.y <= bounds.bottom) )
1289 {
cee24bf7
DS
1290 // found!
1291 return mid;
443e2f09
VZ
1292 }
1293
1294 if ( point.y < bounds.top )
cee24bf7
DS
1295 // index(bounds) greater then key(point)
1296 high = mid - 1;
443e2f09 1297 else
cee24bf7
DS
1298 // index(bounds) less then key(point)
1299 low = mid + 1;
c00fed0e
VZ
1300 }
1301 }
443e2f09 1302
c00fed0e
VZ
1303 return wxNOT_FOUND;
1304}
1305
179e085f 1306#endif