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