]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/listbox.cpp
Avoid an assert if no alignment style is specified
[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
e4db172a
WS
16#include "wx/listbox.h"
17
ad9835c9
WS
18#ifndef WX_PRECOMP
19 #include "wx/dynarray.h"
e4db172a 20 #include "wx/log.h"
987e9419 21 #include "wx/intl.h"
670f9935 22 #include "wx/app.h"
de6185e2 23 #include "wx/utils.h"
f1e01716 24 #include "wx/button.h"
9eddec69 25 #include "wx/settings.h"
ad9835c9
WS
26#endif
27
422644a3 28#include "wx/toplevel.h"
e9576ca5 29
b4726a58
SC
30IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
31
32BEGIN_EVENT_TABLE(wxListBox, wxControl)
33END_EVENT_TABLE()
34
fdd4e6cc 35#include "wx/mac/uma.h"
ad9835c9
WS
36#include "wx/dynarray.h"
37#include "wx/arrstr.h"
b4726a58
SC
38
39// ============================================================================
6cce68ea 40// list box control implementation
b4726a58 41// ============================================================================
e9576ca5 42
6cce68ea 43wxListBox::wxListBox()
83ce5634 44{
83ce5634
SC
45}
46
6cce68ea
SC
47bool wxListBox::Create(
48 wxWindow *parent,
49 wxWindowID id,
50 const wxPoint& pos,
51 const wxSize& size,
52 const wxArrayString& choices,
53 long style,
54 const wxValidator& validator,
55 const wxString& name )
facd6764 56{
6cce68ea 57 wxCArrayString chs(choices);
cee24bf7 58
6cce68ea
SC
59 return Create(
60 parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
61 style, validator, name );
62}
c6179a84 63
ad9835c9
WS
64wxMacListControl* wxListBox::GetPeer() const
65{
66 return dynamic_cast<wxMacListControl*>(m_peer);
facd6764 67}
fe3dc505 68
6cce68ea
SC
69bool wxListBox::Create(
70 wxWindow *parent,
71 wxWindowID id,
72 const wxPoint& pos,
73 const wxSize& size,
74 int n,
75 const wxString choices[],
76 long style,
77 const wxValidator& validator,
78 const wxString& name )
b4726a58 79{
6cce68ea 80 m_macIsUserPane = false;
b4726a58 81
6cce68ea
SC
82 wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
83 wxT("only a single listbox selection mode can be specified") );
b4726a58 84
6cce68ea
SC
85 if ( !wxListBoxBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
86 return false;
ad9835c9 87
6cce68ea
SC
88 wxMacDataBrowserListControl* control = new wxMacDataBrowserListControl( this, pos, size, style );
89 control->SetClientDataType( m_clientDataItemsType );
90 m_peer = control;
cee24bf7 91
6cce68ea 92 MacPostControlCreate( pos, size );
b4726a58 93
6cce68ea 94 InsertItems( n, choices, 0 );
b4726a58 95
6cce68ea
SC
96 // Needed because it is a wxControlWithItems
97 SetBestSize( size );
b4726a58 98
6cce68ea
SC
99 return true;
100}
cee24bf7 101
6cce68ea
SC
102wxListBox::~wxListBox()
103{
104 FreeData();
105 m_peer->SetReference( 0 );
106}
b4726a58 107
6cce68ea
SC
108void wxListBox::FreeData()
109{
110 GetPeer()->MacClear();
111}
b4726a58 112
6cce68ea
SC
113void wxListBox::DoSetFirstItem(int n)
114{
115 GetPeer()->MacScrollTo( n );
116}
b4726a58 117
6cce68ea
SC
118void wxListBox::EnsureVisible(int n)
119{
120 GetPeer()->MacScrollTo( n );
b4726a58 121}
cee24bf7 122
6cce68ea 123void wxListBox::Delete(unsigned int n)
b4726a58 124{
6cce68ea
SC
125 wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::Delete") );
126
127 GetPeer()->MacDelete( n );
b4726a58
SC
128}
129
6cce68ea 130int wxListBox::DoAppend(const wxString& item)
b4726a58 131{
6cce68ea 132 InvalidateBestSize();
b4726a58 133
6cce68ea
SC
134 return GetPeer()->MacAppend( item );
135}
cee24bf7 136
6cce68ea
SC
137void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
138{
139 Clear();
ad9835c9 140
6cce68ea 141 unsigned int n = choices.GetCount();
cee24bf7 142
6cce68ea 143 for ( size_t i = 0; i < n; ++i )
b4726a58 144 {
6cce68ea 145 if ( clientData )
b4726a58 146 {
6cce68ea 147 Append( choices[i], clientData[i] );
b4726a58 148 }
6cce68ea
SC
149 else
150 Append( choices[i] );
b4726a58 151 }
cee24bf7 152
b4726a58
SC
153}
154
6cce68ea 155int wxListBox::FindString(const wxString& s, bool bCase) const
b4726a58 156{
6cce68ea 157 for ( size_t i = 0; i < GetCount(); ++ i )
b4726a58 158 {
6cce68ea
SC
159 if (s.IsSameAs( GetString( i ), bCase) )
160 return (int)i;
b4726a58
SC
161 }
162
6cce68ea 163 return wxNOT_FOUND;
b4726a58
SC
164}
165
6cce68ea 166void wxListBox::Clear()
b4726a58 167{
6cce68ea
SC
168 FreeData();
169}
b4726a58 170
6cce68ea
SC
171void wxListBox::DoSetSelection(int n, bool select)
172{
173 wxCHECK_RET( n == wxNOT_FOUND || IsValid(n),
174 wxT("invalid index in wxListBox::SetSelection") );
b4726a58 175
6cce68ea
SC
176 if ( n == wxNOT_FOUND )
177 GetPeer()->MacDeselectAll();
178 else
179 GetPeer()->MacSetSelection( n, select );
180}
b4726a58 181
6cce68ea
SC
182bool wxListBox::IsSelected(int n) const
183{
184 wxCHECK_MSG( IsValid(n), false, wxT("invalid index in wxListBox::Selected") );
cee24bf7 185
6cce68ea 186 return GetPeer()->MacIsSelected( n );
b4726a58
SC
187}
188
6cce68ea 189void *wxListBox::DoGetItemClientData(unsigned int n) const
b4726a58 190{
6cce68ea
SC
191 wxCHECK_MSG( IsValid(n), NULL, wxT("invalid index in wxListBox::GetClientData"));
192 return GetPeer()->MacGetClientData( n );
b4726a58
SC
193}
194
6cce68ea 195wxClientData *wxListBox::DoGetItemClientObject(unsigned int n) const
b4726a58 196{
6cce68ea 197 return (wxClientData*)DoGetItemClientData( n );
b4726a58
SC
198}
199
6cce68ea 200void wxListBox::DoSetItemClientData(unsigned int n, void *clientData)
b4726a58 201{
6cce68ea
SC
202 wxCHECK_RET( IsValid(n), wxT("invalid index in wxListBox::SetClientData") );
203 GetPeer()->MacSetClientData( n , clientData);
b4726a58
SC
204}
205
6cce68ea 206void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
b4726a58 207{
6cce68ea 208 DoSetItemClientData(n, clientData);
b4726a58
SC
209}
210
6cce68ea
SC
211// Return number of selections and an array of selected integers
212int wxListBox::GetSelections(wxArrayInt& aSelections) const
b4726a58 213{
6cce68ea
SC
214 return GetPeer()->MacGetSelections( aSelections );
215}
cee24bf7 216
6cce68ea
SC
217// Get single selection, for single choice list items
218int wxListBox::GetSelection() const
219{
220 return GetPeer()->MacGetSelection();
b4726a58
SC
221}
222
6cce68ea
SC
223// Find string for position
224wxString wxListBox::GetString(unsigned int n) const
b4726a58 225{
6cce68ea
SC
226 wxCHECK_MSG( IsValid(n), wxEmptyString, wxT("invalid index in wxListBox::GetString") );
227 return GetPeer()->MacGetString(n);
b4726a58
SC
228}
229
6cce68ea 230void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
b4726a58 231{
6cce68ea 232 wxCHECK_RET( IsValidInsert(pos), wxT("invalid index in wxListBox::InsertItems") );
cee24bf7 233
6cce68ea
SC
234 InvalidateBestSize();
235
236 GetPeer()->MacInsert( pos, items );
b4726a58
SC
237}
238
6cce68ea 239void wxListBox::SetString(unsigned int n, const wxString& s)
b4726a58 240{
6cce68ea
SC
241 GetPeer()->MacSetString( n, s );
242}
b4726a58 243
6cce68ea
SC
244wxSize wxListBox::DoGetBestSize() const
245{
246 int lbWidth = 100; // some defaults
247 int lbHeight = 110;
248 int wLine;
b4726a58 249
b4726a58 250 {
6cce68ea
SC
251 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef)MacGetTopLevelWindowRef() ) );
252
253 // TODO: clean this up
254 if ( m_font.Ok() )
b4726a58 255 {
6cce68ea
SC
256 ::TextFont( m_font.MacGetFontNum() );
257 ::TextSize( m_font.MacGetFontSize() );
258 ::TextFace( m_font.MacGetFontStyle() );
259 }
260 else
261 {
262 ::TextFont( kFontIDMonaco );
263 ::TextSize( 9 );
264 ::TextFace( 0 );
b4726a58 265 }
cee24bf7 266
6cce68ea
SC
267 // Find the widest line
268 for (unsigned int i = 0; i < GetCount(); i++)
269 {
270 wxString str( GetString( i ) );
b4726a58 271
6cce68ea
SC
272#if wxUSE_UNICODE
273 Point bounds = {0, 0};
274 SInt16 baseline;
b4726a58 275
6cce68ea
SC
276 // NB: what if m_font.Ok() == false ???
277 ::GetThemeTextDimensions(
278 wxMacCFStringHolder( str, m_font.GetEncoding() ),
279 kThemeCurrentPortFont,
280 kThemeStateActive,
281 false,
282 &bounds,
283 &baseline );
284 wLine = bounds.h;
285#else
286 wLine = ::TextWidth( str.c_str(), 0, str.length() );
287#endif
b4726a58 288
6cce68ea
SC
289 lbWidth = wxMax( lbWidth, wLine );
290 }
b4726a58 291
6cce68ea
SC
292 // Add room for the scrollbar
293 lbWidth += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );
b4726a58 294
6cce68ea
SC
295 // And just a bit more
296 int cy = 12;
297 int cx = ::TextWidth( "X", 0, 1 );
298 lbWidth += cx;
b4726a58 299
6cce68ea
SC
300 // don't make the listbox too tall (limit height to around 10 items)
301 // but don't make it too small neither
302 lbHeight = wxMax( (cy + 4) * wxMin( wxMax( GetCount(), 3 ), 10 ), 70 );
303 }
b4726a58 304
6cce68ea 305 return wxSize( lbWidth, lbHeight );
b4726a58
SC
306}
307
6cce68ea 308unsigned int wxListBox::GetCount() const
b4726a58 309{
6cce68ea 310 return GetPeer()->MacGetCount();
b4726a58
SC
311}
312
6cce68ea 313void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
b4726a58 314{
6cce68ea 315 wxControl::Refresh( eraseBack, rect );
b4726a58
SC
316}
317
6cce68ea
SC
318// Some custom controls depend on this
319/* static */ wxVisualAttributes
320wxListBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
b4726a58 321{
6cce68ea 322 wxVisualAttributes attr;
b4726a58 323
6cce68ea
SC
324 attr.colFg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
325 attr.colBg = wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX );
326 attr.font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
b4726a58 327
6cce68ea 328 return attr;
b4726a58
SC
329}
330
6cce68ea 331int wxListBox::DoListHitTest(const wxPoint& inpoint) const
b4726a58 332{
6cce68ea 333 OSStatus err;
b4726a58 334
6cce68ea
SC
335 // There are few reasons why this is complicated:
336 // 1) There is no native HitTest function for Mac
337 // 2) GetDataBrowserItemPartBounds only works on visible items
338 // 3) We can't do it through GetDataBrowserTableView[Item]RowHeight
339 // because what it returns is basically inaccurate in the context
340 // of the coordinates we want here, but we use this as a guess
341 // for where the first visible item lies
b4726a58 342
6cce68ea 343 wxPoint point = inpoint;
b4726a58 344
6cce68ea
SC
345 // interestingly enough 10.2 (and below?) have GetDataBrowserItemPartBounds
346 // giving root window coordinates but 10.3 and above give client coordinates
347 // so we only compare using root window coordinates on 10.3 and up
348 if ( UMAGetSystemVersion() < 0x1030 )
349 MacClientToRootWindow(&point.x, &point.y);
b4726a58 350
6cce68ea
SC
351 // get column property ID (req. for call to itempartbounds)
352 DataBrowserTableViewColumnID colId = 0;
353 err = GetDataBrowserTableViewColumnProperty(m_peer->GetControlRef(), 0, &colId);
354 wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewColumnProperty"));
b4726a58 355
6cce68ea
SC
356 // OK, first we need to find the first visible item we have -
357 // this will be the "low" for our binary search. There is no real
358 // easy way around this, as we will need to do a SLOW linear search
359 // until we find a visible item, but we can do a cheap calculation
360 // via the row height to speed things up a bit
361 UInt32 scrollx, scrolly;
362 err = GetDataBrowserScrollPosition(m_peer->GetControlRef(), &scrollx, &scrolly);
363 wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserScrollPosition"));
b4726a58 364
6cce68ea
SC
365 UInt16 height;
366 err = GetDataBrowserTableViewRowHeight(m_peer->GetControlRef(), &height);
367 wxCHECK_MSG(err == noErr, wxNOT_FOUND, wxT("Unexpected error from GetDataBrowserTableViewRowHeight"));
b4726a58 368
6cce68ea
SC
369 // these indices are 0-based, as usual, so we need to add 1 to them when
370 // passing them to data browser functions which use 1-based indices
371 int low = scrolly / height,
372 high = GetCount() - 1;
b4726a58 373
6cce68ea
SC
374 // search for the first visible item (note that the scroll guess above
375 // is the low bounds of where the item might lie so we only use that as a
376 // starting point - we should reach it within 1 or 2 iterations of the loop)
377 while ( low <= high )
378 {
379 Rect bounds;
380 err = GetDataBrowserItemPartBounds(
381 m_peer->GetControlRef(), low + 1, colId,
382 kDataBrowserPropertyEnclosingPart,
383 &bounds); // note +1 to translate to Mac ID
384 if ( err == noErr )
385 break;
b4726a58 386
6cce68ea
SC
387 // errDataBrowserItemNotFound is expected as it simply means that the
388 // item is not currently visible -- but other errors are not
389 wxCHECK_MSG( err == errDataBrowserItemNotFound, wxNOT_FOUND,
390 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
789ae0cf 391
6cce68ea
SC
392 low++;
393 }
de1b0aeb 394
6cce68ea
SC
395 // NOW do a binary search for where the item lies, searching low again if
396 // we hit an item that isn't visible
397 while ( low <= high )
789ae0cf 398 {
6cce68ea 399 int mid = (low + high) / 2;
fdd4e6cc 400
6cce68ea
SC
401 Rect bounds;
402 err = GetDataBrowserItemPartBounds(
403 m_peer->GetControlRef(), mid + 1, colId,
404 kDataBrowserPropertyEnclosingPart,
405 &bounds); //note +1 to trans to mac id
406 wxCHECK_MSG( err == noErr || err == errDataBrowserItemNotFound,
407 wxNOT_FOUND,
408 wxT("Unexpected error from GetDataBrowserItemPartBounds") );
789ae0cf 409
6cce68ea
SC
410 if ( err == errDataBrowserItemNotFound )
411 {
412 // item not visible, attempt to find a visible one
413 // search lower
414 high = mid - 1;
415 }
416 else // visible item, do actual hitttest
417 {
418 // if point is within the bounds, return this item (since we assume
419 // all x coords of items are equal we only test the x coord in
420 // equality)
421 if ((point.x >= bounds.left && point.x <= bounds.right) &&
422 (point.y >= bounds.top && point.y <= bounds.bottom) )
423 {
424 // found!
425 return mid;
426 }
fdd4e6cc 427
6cce68ea
SC
428 if ( point.y < bounds.top )
429 // index(bounds) greater then key(point)
430 high = mid - 1;
431 else
432 // index(bounds) less then key(point)
433 low = mid + 1;
434 }
435 }
fdd4e6cc 436
6cce68ea 437 return wxNOT_FOUND;
789ae0cf 438}
b4726a58 439
b4726a58 440// ============================================================================
6cce68ea 441// data browser based implementation
b4726a58 442// ============================================================================
fe3dc505 443
6cce68ea
SC
444const short kTextColumnId = 1024;
445const short kNumericOrderColumnId = 1025;
446
447wxMacListBoxItem::wxMacListBoxItem()
fe3dc505 448{
6cce68ea
SC
449 m_data = NULL;
450 m_order = 0;
fe3dc505
SC
451}
452
6cce68ea 453wxMacListBoxItem::~wxMacListBoxItem()
fe3dc505 454{
fe3dc505
SC
455}
456
ad9835c9 457void wxMacListBoxItem::SetOrder( SInt32 order )
facd6764 458{
6cce68ea 459 m_order = order;
facd6764
SC
460}
461
ad9835c9 462SInt32 wxMacListBoxItem::GetOrder() const
facd6764 463{
6cce68ea 464 return m_order;
b4726a58 465}
fdd4e6cc 466
ad9835c9 467void wxMacListBoxItem::SetData( void* data)
b4726a58 468{
6cce68ea 469 m_data = data;
facd6764
SC
470}
471
ad9835c9 472void* wxMacListBoxItem::GetData() const
facd6764 473{
6cce68ea 474 return m_data;
facd6764
SC
475}
476
6cce68ea 477void wxMacListBoxItem::SetLabel( const wxString& str)
facd6764 478{
6cce68ea
SC
479 m_label = str;
480 m_cfLabel.Assign( str , wxLocale::GetSystemEncoding());
facd6764
SC
481}
482
6cce68ea 483const wxString& wxMacListBoxItem::GetLabel() const
facd6764 484{
6cce68ea 485 return m_label;
facd6764
SC
486}
487
ad9835c9
WS
488bool wxMacListBoxItem::IsLessThan(wxMacDataItemBrowserControl *owner ,
489 const wxMacDataItem* rhs,
6cce68ea 490 DataBrowserPropertyID sortProperty) const
facd6764 491{
6cce68ea
SC
492 const wxMacListBoxItem* otherItem = dynamic_cast<const wxMacListBoxItem*>(rhs);
493 bool retval = false;
494 switch (sortProperty)
b4726a58 495 {
6cce68ea
SC
496 case kTextColumnId:
497 retval = m_label.CmpNoCase( otherItem->m_label) < 0;
498 break;
facd6764 499
6cce68ea
SC
500 case kNumericOrderColumnId:
501 retval = m_order < otherItem->m_order;
502 break;
9f884528 503
6cce68ea
SC
504 default:
505 break;
506 };
facd6764 507
6cce68ea 508 return retval;
facd6764
SC
509}
510
6cce68ea
SC
511OSStatus wxMacListBoxItem::GetSetData( wxMacDataItemBrowserControl *owner ,
512 DataBrowserPropertyID property,
513 DataBrowserItemDataRef itemData,
ad9835c9 514 bool changeValue )
facd6764 515{
6cce68ea
SC
516 OSStatus err = errDataBrowserPropertyNotSupported;
517 wxListBox *list = wxDynamicCast( owner->GetPeer() , wxListBox );
518 wxCHECK_MSG( list != NULL , errDataBrowserPropertyNotSupported , wxT("Listbox expected"));
c6179a84 519
6cce68ea 520 if ( !changeValue )
facd6764 521 {
6cce68ea 522 switch (property)
b4726a58 523 {
6cce68ea
SC
524 case kTextColumnId:
525 err = ::SetDataBrowserItemDataText( itemData, m_cfLabel );
526 err = noErr;
527 break;
528
529 case kNumericOrderColumnId:
530 err = ::SetDataBrowserItemDataValue( itemData, m_order );
531 err = noErr;
532 break;
533
534 default:
535 break;
b4726a58 536 }
facd6764 537 }
6cce68ea 538 else
cee24bf7 539 {
6cce68ea 540 switch (property)
cee24bf7 541 {
6cce68ea
SC
542 // no editable props here
543 default:
544 break;
b4726a58 545 }
6cce68ea
SC
546 }
547
548 return err;
549}
cee24bf7 550
ad9835c9 551void wxMacListBoxItem::Notification(wxMacDataItemBrowserControl *owner ,
6cce68ea
SC
552 DataBrowserItemNotification message,
553 DataBrowserItemDataRef itemData ) const
554{
555 wxMacDataBrowserListControl *lb = dynamic_cast<wxMacDataBrowserListControl*>(owner);
b4726a58 556
6cce68ea 557 // we want to depend on as little as possible to make sure tear-down of controls is safe
ad9835c9 558
6cce68ea
SC
559 if ( message == kDataBrowserItemRemoved)
560 {
561 if ( lb != NULL && lb->GetClientDataType() == wxClientData_Object )
cee24bf7 562 {
6cce68ea 563 delete (wxClientData*) (m_data);
b4726a58 564 }
6cce68ea
SC
565
566 delete this;
567 return;
b4726a58 568 }
ad9835c9 569
6cce68ea
SC
570 wxListBox *list = wxDynamicCast( owner->GetPeer() , wxListBox );
571 wxCHECK_RET( list != NULL , wxT("Listbox expected"));
facd6764 572
6cce68ea
SC
573 bool trigger = false;
574 wxCommandEvent event( wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() );
575 switch (message)
facd6764 576 {
6cce68ea
SC
577 case kDataBrowserItemDeselected:
578 if ( list->HasMultipleSelection() )
579 trigger = !lb->IsSelectionSuppressed();
580 break;
fdd4e6cc 581
6cce68ea
SC
582 case kDataBrowserItemSelected:
583 trigger = !lb->IsSelectionSuppressed();
584 break;
facd6764 585
6cce68ea
SC
586 case kDataBrowserItemDoubleClicked:
587 event.SetEventType( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED );
588 trigger = true;
589 break;
facd6764 590
6cce68ea
SC
591 default:
592 break;
593 }
c6179a84 594
6cce68ea
SC
595 if ( trigger )
596 {
597 event.SetEventObject( list );
598 if ( list->HasClientObjectData() )
599 event.SetClientObject( (wxClientData*) m_data );
600 else if ( list->HasClientUntypedData() )
601 event.SetClientData( m_data );
602 event.SetString( m_label );
603 event.SetInt( owner->GetLineFromItem( this ) );
604 event.SetExtraLong( list->HasMultipleSelection() ? message == kDataBrowserItemSelected : true );
605 wxPostEvent( list->GetEventHandler(), event );
606
607 // direct notification is not always having the listbox GetSelection() having in synch with event
608 // list->GetEventHandler()->ProcessEvent(event);
609 }
facd6764
SC
610}
611
6cce68ea
SC
612wxMacDataBrowserListControl::wxMacDataBrowserListControl( wxListBox *peer, const wxPoint& pos, const wxSize& size, long style)
613 : wxMacDataItemBrowserControl( peer, pos, size, style )
facd6764 614{
6cce68ea
SC
615 OSStatus err = noErr;
616 m_clientDataItemsType = wxClientData_None;
617 m_stringSorted = style & wxLB_SORT;
ad9835c9 618
6cce68ea
SC
619 DataBrowserSelectionFlags options = kDataBrowserDragSelect;
620 if ( style & wxLB_MULTIPLE )
621 {
622 options |= kDataBrowserAlwaysExtendSelection | kDataBrowserCmdTogglesSelection;
623 }
624 else if ( style & wxLB_EXTENDED )
625 {
626 // default behaviour
627 }
628 else
629 {
630 options |= kDataBrowserSelectOnlyOne;
631 }
632 err = SetSelectionFlags( options );
633 verify_noerr( err );
ad9835c9 634
6cce68ea
SC
635 DataBrowserListViewColumnDesc columnDesc;
636 columnDesc.headerBtnDesc.titleOffset = 0;
637 columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
facd6764 638
6cce68ea
SC
639 columnDesc.headerBtnDesc.btnFontStyle.flags =
640 kControlUseFontMask | kControlUseJustMask;
8228b893 641
6cce68ea
SC
642 columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent;
643 columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault;
644 columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
645 columnDesc.headerBtnDesc.btnFontStyle.style = normal;
646 columnDesc.headerBtnDesc.titleString = NULL;
c6179a84 647
6cce68ea
SC
648 columnDesc.headerBtnDesc.minimumWidth = 0;
649 columnDesc.headerBtnDesc.maximumWidth = 10000;
facd6764 650
6cce68ea
SC
651 columnDesc.propertyDesc.propertyID = kTextColumnId;
652 columnDesc.propertyDesc.propertyType = kDataBrowserTextType;
653 columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn;
654#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
655 columnDesc.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn;
656#endif
facd6764 657
6cce68ea 658 verify_noerr( AddColumn( &columnDesc, kDataBrowserListViewAppendColumn ) );
c6179a84 659
6cce68ea
SC
660 columnDesc.headerBtnDesc.minimumWidth = 0;
661 columnDesc.headerBtnDesc.maximumWidth = 0;
662 columnDesc.propertyDesc.propertyID = kNumericOrderColumnId;
663 columnDesc.propertyDesc.propertyType = kDataBrowserPropertyRelevanceRankPart;
664 columnDesc.propertyDesc.propertyFlags = kDataBrowserTableViewSelectionColumn;
665#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
666 columnDesc.propertyDesc.propertyFlags |= kDataBrowserListViewTypeSelectColumn;
cee24bf7
DS
667#endif
668
6cce68ea 669 verify_noerr( AddColumn( &columnDesc, kDataBrowserListViewAppendColumn ) );
c6179a84 670
6cce68ea
SC
671 SetDataBrowserSortProperty( m_controlRef , kTextColumnId);
672 if ( m_stringSorted )
673 {
674 SetDataBrowserSortProperty( m_controlRef , kTextColumnId);
675 SetDataBrowserSortOrder( m_controlRef , kDataBrowserOrderIncreasing);
676 }
facd6764 677 else
6cce68ea
SC
678 {
679 SetDataBrowserSortProperty( m_controlRef , kNumericOrderColumnId);
680 SetDataBrowserSortOrder( m_controlRef , kDataBrowserOrderIncreasing);
681 }
facd6764 682
6cce68ea
SC
683 verify_noerr( AutoSizeColumns() );
684 verify_noerr( SetHiliteStyle(kDataBrowserTableViewFillHilite ) );
685 verify_noerr( SetHeaderButtonHeight( 0 ) );
686 err = SetHasScrollBars( (style & wxHSCROLL) != 0 , true );
687#if 0
688 // shouldn't be necessary anymore under 10.2
689 m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean)false );
690 m_peer->SetNeedsFocusRect( true );
691#endif
facd6764
SC
692}
693
6cce68ea 694wxMacDataBrowserListControl::~wxMacDataBrowserListControl()
facd6764 695{
facd6764
SC
696}
697
6cce68ea 698
ad9835c9 699wxMacListBoxItem* wxMacDataBrowserListControl::CreateItem()
facd6764 700{
6cce68ea
SC
701 return new wxMacListBoxItem();
702}
55ae2833 703
6cce68ea 704wxListBox * wxMacDataBrowserListControl::GetPeer() const
ad9835c9
WS
705{
706 return wxDynamicCast( wxMacControl::GetPeer() , wxListBox );
facd6764
SC
707}
708
ad9835c9 709wxClientDataType wxMacDataBrowserListControl::GetClientDataType() const
facd6764 710{
6cce68ea
SC
711 return m_clientDataItemsType;
712}
ad9835c9 713void wxMacDataBrowserListControl::SetClientDataType(wxClientDataType clientDataItemsType)
6cce68ea
SC
714{
715 m_clientDataItemsType = clientDataItemsType;
716}
c6179a84 717
ad9835c9 718unsigned int wxMacDataBrowserListControl::MacGetCount() const
6cce68ea 719{
f028b0d9 720 return GetItemCount(wxMacDataBrowserRootContainer,false,kDataBrowserItemAnyState);
facd6764
SC
721}
722
6cce68ea 723void wxMacDataBrowserListControl::MacDelete( unsigned int n )
facd6764 724{
6cce68ea
SC
725 wxMacListBoxItem* item = (wxMacListBoxItem*)GetItemFromLine( n );
726 RemoveItem( wxMacDataBrowserRootContainer, item );
facd6764
SC
727}
728
6cce68ea 729void wxMacDataBrowserListControl::MacInsert( unsigned int n, const wxString& text)
facd6764 730{
6cce68ea
SC
731 wxMacListBoxItem* newItem = CreateItem();
732 newItem->SetLabel( text );
facd6764 733
6cce68ea 734 if ( !m_stringSorted )
facd6764 735 {
6cce68ea
SC
736 // increase the order of the lines to be shifted
737 unsigned int lines = MacGetCount();
738 for ( unsigned int i = n; i < lines; ++i)
facd6764 739 {
6cce68ea
SC
740 wxMacListBoxItem* iter = (wxMacListBoxItem*) GetItemFromLine(i);
741 iter->SetOrder( iter->GetOrder() + 1 );
facd6764 742 }
ad9835c9 743
6cce68ea
SC
744 SInt32 frontLineOrder = 0;
745 if ( n > 0 )
facd6764 746 {
6cce68ea
SC
747 wxMacListBoxItem* iter = (wxMacListBoxItem*) GetItemFromLine(n-1);
748 frontLineOrder = iter->GetOrder();
facd6764 749 }
6cce68ea
SC
750 newItem->SetOrder( frontLineOrder + 1 );
751 }
ad9835c9 752
6cce68ea
SC
753 AddItem( wxMacDataBrowserRootContainer, newItem );
754}
c6179a84 755
6cce68ea
SC
756void wxMacDataBrowserListControl::MacInsert( unsigned int n, const wxArrayString& items)
757{
758 size_t itemsCount = items.GetCount();
759 if ( itemsCount == 0 )
760 return;
ad9835c9 761
6cce68ea 762 SInt32 frontLineOrder = 0;
ad9835c9 763
6cce68ea
SC
764 if ( !m_stringSorted )
765 {
766 // increase the order of the lines to be shifted
767 unsigned int lines = MacGetCount();
768 for ( unsigned int i = n; i < lines; ++i)
fdd4e6cc 769 {
6cce68ea
SC
770 wxMacListBoxItem* iter = (wxMacListBoxItem*) GetItemFromLine(i);
771 iter->SetOrder( iter->GetOrder() + itemsCount );
772 }
773 if ( n > 0 )
774 {
775 wxMacListBoxItem* iter = (wxMacListBoxItem*) GetItemFromLine(n-1);
776 frontLineOrder = iter->GetOrder();
facd6764 777 }
6cce68ea 778 }
c6179a84 779
6cce68ea
SC
780 wxArrayMacDataItemPtr ids;
781 ids.SetCount( itemsCount );
c6179a84 782
6cce68ea
SC
783 for ( unsigned int i = 0; i < itemsCount; ++i )
784 {
785 wxMacListBoxItem* item = CreateItem();
786 item->SetLabel( items[i]);
787 if ( !m_stringSorted )
788 item->SetOrder( frontLineOrder + 1 + i );
c6179a84 789
6cce68ea 790 ids[i] = item;
facd6764
SC
791 }
792
6cce68ea 793 AddItems( wxMacDataBrowserRootContainer, ids );
facd6764
SC
794}
795
6cce68ea 796int wxMacDataBrowserListControl::MacAppend( const wxString& text)
facd6764 797{
6cce68ea
SC
798 wxMacListBoxItem* item = CreateItem();
799 item->SetLabel( text );
800 if ( !m_stringSorted )
801 {
802 unsigned int lines = MacGetCount();
803 if ( lines == 0 )
804 item->SetOrder( 1 );
805 else
806 {
807 wxMacListBoxItem* frontItem = (wxMacListBoxItem*) GetItemFromLine(lines-1);
808 item->SetOrder( frontItem->GetOrder() + 1 );
809 }
810 }
811 AddItem( wxMacDataBrowserRootContainer, item );
812
813 return GetLineFromItem(item);
facd6764
SC
814}
815
6cce68ea 816void wxMacDataBrowserListControl::MacClear()
facd6764 817{
6cce68ea
SC
818 wxMacDataItemBrowserSelectionSuppressor suppressor(this);
819 RemoveAllItems(wxMacDataBrowserRootContainer);
facd6764
SC
820}
821
6cce68ea 822void wxMacDataBrowserListControl::MacDeselectAll()
b6a20a20 823{
6cce68ea
SC
824 wxMacDataItemBrowserSelectionSuppressor suppressor(this);
825 SetSelectedAllItems( kDataBrowserItemsRemove );
b6a20a20
RD
826}
827
6cce68ea 828void wxMacDataBrowserListControl::MacSetSelection( unsigned int n, bool select )
facd6764 829{
6cce68ea
SC
830 wxMacListBoxItem* item = (wxMacListBoxItem*) GetItemFromLine(n);
831 wxMacDataItemBrowserSelectionSuppressor suppressor(this);
fdd4e6cc 832
6cce68ea
SC
833 if ( IsItemSelected( item ) != select )
834 {
835 if ( select )
836 SetSelectedItem( item, GetPeer()->HasMultipleSelection() ? kDataBrowserItemsAdd : kDataBrowserItemsAssign );
837 else
838 SetSelectedItem( item, kDataBrowserItemsRemove );
839 }
840
841 MacScrollTo( n );
facd6764
SC
842}
843
6cce68ea 844bool wxMacDataBrowserListControl::MacIsSelected( unsigned int n ) const
facd6764 845{
6cce68ea
SC
846 wxMacListBoxItem* item = (wxMacListBoxItem*) GetItemFromLine(n);
847 return IsItemSelected( item );
facd6764
SC
848}
849
6cce68ea
SC
850int wxMacDataBrowserListControl::MacGetSelection() const
851{
852 wxMacDataItemPtr first, last;
853 GetSelectionAnchor( &first, &last );
fdd4e6cc 854
6cce68ea
SC
855 if ( first != NULL )
856 {
857 return GetLineFromItem( first );
858 }
facd6764 859
6cce68ea
SC
860 return -1;
861}
862
863int wxMacDataBrowserListControl::MacGetSelections( wxArrayInt& aSelections ) const
facd6764 864{
6cce68ea
SC
865 aSelections.Empty();
866 wxArrayMacDataItemPtr selectedItems;
867 GetItems( wxMacDataBrowserRootContainer, false , kDataBrowserItemIsSelected, selectedItems);
519cb848 868
6cce68ea 869 int count = selectedItems.GetCount();
e42e45a9 870
6cce68ea
SC
871 for ( int i = 0; i < count; ++i)
872 {
873 aSelections.Add(GetLineFromItem(selectedItems[i]));
874 }
875
876 return count;
facd6764
SC
877}
878
6cce68ea 879void wxMacDataBrowserListControl::MacSetString( unsigned int n, const wxString& text )
443e2f09 880{
6cce68ea
SC
881 // as we don't store the strings we only have to issue a redraw
882 wxMacListBoxItem* item = (wxMacListBoxItem*) GetItemFromLine( n);
883 item->SetLabel( text );
884 UpdateItem( wxMacDataBrowserRootContainer, item , kTextColumnId );
885}
443e2f09 886
6cce68ea
SC
887wxString wxMacDataBrowserListControl::MacGetString( unsigned int n ) const
888{
889 wxMacListBoxItem * item = (wxMacListBoxItem*) GetItemFromLine( n );
890 return item->GetLabel();
891}
cee24bf7 892
ad9835c9 893void wxMacDataBrowserListControl::MacSetClientData( unsigned int n, void * data)
6cce68ea
SC
894{
895 wxMacListBoxItem* item = (wxMacListBoxItem*) GetItemFromLine( n);
896 item->SetData( data );
897 // not displayed, therefore no Update infos to DataBrowser
898}
443e2f09 899
ad9835c9 900void * wxMacDataBrowserListControl::MacGetClientData( unsigned int n) const
6cce68ea
SC
901{
902 wxMacListBoxItem * item = (wxMacListBoxItem*) GetItemFromLine( n );
ad9835c9 903 return item->GetData();
6cce68ea 904}
443e2f09 905
6cce68ea
SC
906void wxMacDataBrowserListControl::MacScrollTo( unsigned int n )
907{
908 RevealItem( GetItemFromLine( n) , kDataBrowserRevealWithoutSelecting );
909}
443e2f09 910
6cce68ea 911#if 0
443e2f09 912
6cce68ea 913// in case we need that one day
443e2f09 914
6cce68ea
SC
915// ============================================================================
916// HIView owner-draw-based implementation
917// ============================================================================
443e2f09 918
6cce68ea
SC
919static pascal void ListBoxDrawProc(
920 ControlRef browser, DataBrowserItemID item, DataBrowserPropertyID property,
921 DataBrowserItemState itemState, const Rect *itemRect, SInt16 depth, Boolean isColorDevice )
922{
923 CFStringRef cfString;
924 ThemeDrawingState themeState;
925 long systemVersion;
443e2f09 926
6cce68ea
SC
927 GetThemeDrawingState( &themeState );
928 cfString = CFStringCreateWithFormat( NULL, NULL, CFSTR("Row %d"), item );
c00fed0e 929
6cce68ea
SC
930 // In this sample we handle the "selected" state; all others fall through to our "active" state
931 if ( itemState == kDataBrowserItemIsSelected )
c00fed0e 932 {
6cce68ea 933 ThemeBrush colorBrushID;
443e2f09 934
6cce68ea
SC
935 // TODO: switch over to wxSystemSettingsNative::GetColour() when kThemeBrushSecondaryHighlightColor
936 // is incorporated Panther DB starts using kThemeBrushSecondaryHighlightColor
937 // for inactive browser highlighting
938 Gestalt( gestaltSystemVersion, &systemVersion );
939 if ( (systemVersion >= 0x00001030) && !IsControlActive( browser ) )
940 colorBrushID = kThemeBrushSecondaryHighlightColor;
941 else
942 colorBrushID = kThemeBrushPrimaryHighlightColor;
443e2f09 943
6cce68ea
SC
944 // First paint the hilite rect, then the text on top
945 SetThemePen( colorBrushID, 32, true );
946 PaintRect( itemRect );
947 SetThemeDrawingState( themeState, false );
c00fed0e 948 }
443e2f09 949
6cce68ea
SC
950 DrawThemeTextBox( cfString, kThemeApplicationFont, kThemeStateActive, true, itemRect, teFlushDefault, NULL );
951 SetThemeDrawingState( themeState, true );
952
953 if ( cfString != NULL )
954 CFRelease( cfString );
c00fed0e
VZ
955}
956
179e085f 957#endif
6cce68ea
SC
958
959
987e9419 960#endif // wxUSE_LISTBOX