remove the selection when SetSelection(-1) is called instead of asserting (as documented)
[wxWidgets.git] / src / mac / carbon / listbox.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: listbox.cpp
3 // Purpose: wxListBox
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "listbox.h"
14 #endif
15
16 #include "wx/app.h"
17 #include "wx/listbox.h"
18 #include "wx/button.h"
19 #include "wx/settings.h"
20 #include "wx/toplevel.h"
21 #include "wx/dynarray.h"
22 #include "wx/log.h"
23
24 #include "wx/utils.h"
25
26 #if !USE_SHARED_LIBRARY
27 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
28
29 BEGIN_EVENT_TABLE(wxListBox, wxControl)
30 #ifndef __WXMAC_OSX__
31 EVT_SIZE( wxListBox::OnSize )
32 EVT_CHAR( wxListBox::OnChar )
33 #endif
34 END_EVENT_TABLE()
35 #endif
36
37 #include "wx/mac/uma.h"
38
39 const short kTextColumnId = 1024 ;
40
41 // new databrowserbased version
42 // because of the limited insert
43 // functionality of DataBrowser,
44 // we just introduce id s corresponding
45 // to the line number
46
47 // Listbox item
48 wxListBox::wxListBox()
49 {
50 m_noItems = 0;
51 m_selected = 0;
52 m_macList = NULL ;
53 }
54
55 bool wxListBox::Create(wxWindow *parent, wxWindowID id,
56 const wxPoint& pos,
57 const wxSize& size,
58 const wxArrayString& choices,
59 long style,
60 const wxValidator& validator,
61 const wxString& name)
62 {
63 wxCArrayString chs(choices);
64
65 return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
66 style, validator, name);
67 }
68
69 #if TARGET_API_MAC_OSX
70 static pascal void DataBrowserItemNotificationProc(ControlRef browser, DataBrowserItemID itemID,
71 DataBrowserItemNotification message, DataBrowserItemDataRef itemData)
72 #else
73 static pascal void DataBrowserItemNotificationProc(ControlRef browser, DataBrowserItemID itemID,
74 DataBrowserItemNotification message)
75 #endif
76 {
77 long ref = GetControlReference( browser ) ;
78 if ( ref )
79 {
80 wxListBox* list = wxDynamicCast( (wxObject*) ref , wxListBox ) ;
81 int i = itemID - 1 ;
82 if (i >= 0 && i < list->GetCount() )
83 {
84 bool trigger = false ;
85 wxCommandEvent event(
86 wxEVT_COMMAND_LISTBOX_SELECTED, list->GetId() );
87 switch( message )
88 {
89 case kDataBrowserItemDeselected :
90 if ( list->HasMultipleSelection() )
91 trigger = true ;
92 break ;
93 case kDataBrowserItemSelected :
94 trigger = true ;
95 break ;
96 case kDataBrowserItemDoubleClicked :
97 event.SetEventType(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED) ;
98 trigger = true ;
99 break ;
100 default :
101 break ;
102 }
103 if ( trigger )
104 {
105 event.SetEventObject( list );
106 if ( list->HasClientObjectData() )
107 event.SetClientObject( list->GetClientObject(i) );
108 else if ( list->HasClientUntypedData() )
109 event.SetClientData( list->GetClientData(i) );
110 event.SetString( list->GetString(i) );
111 event.SetInt(i) ;
112 event.SetExtraLong( list->HasMultipleSelection() ? message == kDataBrowserItemSelected : TRUE );
113 wxPostEvent( list->GetEventHandler() , event ) ;
114 // direct notification is not always having the listbox GetSelection() having in synch with event
115 // list->GetEventHandler()->ProcessEvent(event) ;
116 }
117 }
118 }
119 }
120
121
122 static pascal OSStatus ListBoxGetSetItemData(ControlRef browser,
123 DataBrowserItemID itemID, DataBrowserPropertyID property,
124 DataBrowserItemDataRef itemData, Boolean changeValue)
125 {
126 OSStatus err = errDataBrowserPropertyNotSupported;
127
128 if ( ! changeValue )
129 {
130 switch (property)
131 {
132
133 case kTextColumnId:
134 {
135 long ref = GetControlReference( browser ) ;
136 if ( ref )
137 {
138 wxListBox* list = wxDynamicCast( (wxObject*) ref , wxListBox ) ;
139 int i = itemID - 1 ;
140 if (i >= 0 && i < list->GetCount() )
141 {
142 wxMacCFStringHolder cf( list->GetString(i) , list->GetFont().GetEncoding() ) ;
143 verify_noerr( ::SetDataBrowserItemDataText( itemData , cf ) ) ;
144 err = noErr ;
145 }
146 }
147 }
148 break;
149
150 default:
151
152 break;
153 }
154 }
155
156 return err;
157 }
158 bool wxListBox::Create(wxWindow *parent, wxWindowID id,
159 const wxPoint& pos,
160 const wxSize& size,
161 int n, const wxString choices[],
162 long style,
163 const wxValidator& validator,
164 const wxString& name)
165 {
166 m_macIsUserPane = FALSE ;
167
168 wxASSERT_MSG( !(style & wxLB_MULTIPLE) || !(style & wxLB_EXTENDED),
169 _T("only one of listbox selection modes can be specified") );
170
171 if ( !wxListBoxBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
172 return false;
173
174 m_noItems = 0 ; // this will be increased by our append command
175 m_selected = 0;
176
177 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
178
179 m_peer = new wxMacControl() ;
180 verify_noerr( ::CreateDataBrowserControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, kDataBrowserListView , m_peer->GetControlRefAddr() ) );
181
182 DataBrowserSelectionFlags options = kDataBrowserDragSelect ;
183 if ( style & wxLB_MULTIPLE )
184 {
185 options += kDataBrowserAlwaysExtendSelection + kDataBrowserCmdTogglesSelection ;
186 }
187 else if ( style & wxLB_EXTENDED )
188 {
189 // default behaviour
190 }
191 else
192 {
193 options += kDataBrowserSelectOnlyOne ;
194 }
195 verify_noerr(m_peer->SetSelectionFlags( options ) );
196
197 DataBrowserListViewColumnDesc columnDesc ;
198 columnDesc.headerBtnDesc.titleOffset = 0;
199 columnDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
200
201 columnDesc.headerBtnDesc.btnFontStyle.flags =
202 kControlUseFontMask | kControlUseJustMask;
203
204 columnDesc.headerBtnDesc.btnContentInfo.contentType = kControlNoContent;
205 columnDesc.propertyDesc.propertyType = kDataBrowserTextType;
206 columnDesc.headerBtnDesc.btnFontStyle.just = teFlushDefault;
207 columnDesc.headerBtnDesc.minimumWidth = 0;
208 columnDesc.headerBtnDesc.maximumWidth = 10000;
209
210 columnDesc.headerBtnDesc.btnFontStyle.font = kControlFontViewSystemFont;
211 columnDesc.headerBtnDesc.btnFontStyle.style = normal;
212 columnDesc.headerBtnDesc.titleString = NULL ; // CFSTR( "" );
213
214 columnDesc.propertyDesc.propertyID = kTextColumnId;
215 columnDesc.propertyDesc.propertyType = kDataBrowserTextType;
216 columnDesc.propertyDesc.propertyFlags =
217 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
218 kDataBrowserListViewTypeSelectColumn |
219 #endif
220 kDataBrowserTableViewSelectionColumn ;
221
222
223 verify_noerr(m_peer->AddListViewColumn( &columnDesc, kDataBrowserListViewAppendColumn) ) ;
224 verify_noerr(m_peer->AutoSizeListViewColumns() ) ;
225 verify_noerr(m_peer->SetHasScrollBars(false , true ) ) ;
226 verify_noerr(m_peer->SetTableViewHiliteStyle(kDataBrowserTableViewFillHilite ) ) ;
227 verify_noerr(m_peer->SetListViewHeaderBtnHeight( 0 ) ) ;
228 DataBrowserCallbacks callbacks ;
229
230 callbacks.version = kDataBrowserLatestCallbacks;
231
232 InitDataBrowserCallbacks(&callbacks);
233
234 callbacks.u.v1.itemDataCallback =
235 NewDataBrowserItemDataUPP(ListBoxGetSetItemData);
236
237 callbacks.u.v1.itemNotificationCallback =
238 #if TARGET_API_MAC_OSX
239 (DataBrowserItemNotificationUPP) NewDataBrowserItemNotificationWithItemUPP(DataBrowserItemNotificationProc) ;
240 #else
241 NewDataBrowserItemNotificationUPP(DataBrowserItemNotificationProc) ;
242 #endif
243 m_peer->SetCallbacks( &callbacks);
244
245 #if TARGET_API_MAC_OSX
246 // there is a redraw bug in 10.2.X
247 if ( UMAGetSystemVersion() < 0x1030 )
248 m_peer->SetData( kControlNoPart, kControlDataBrowserIncludesFrameAndFocusTag, (Boolean) false ) ;
249 #endif
250
251 MacPostControlCreate(pos,size) ;
252
253 for ( int i = 0 ; i < n ; i++ )
254 {
255 Append( choices[i] ) ;
256 }
257
258 SetBestSize(size); // Needed because it is a wxControlWithItems
259
260 return TRUE;
261 }
262
263 wxListBox::~wxListBox()
264 {
265 m_peer->SetReference( NULL ) ;
266 FreeData() ;
267 // avoid access during destruction
268 if ( m_macList )
269 {
270 m_macList = NULL ;
271 }
272 }
273
274 void wxListBox::FreeData()
275 {
276 #if wxUSE_OWNER_DRAWN
277 if ( m_windowStyle & wxLB_OWNERDRAW )
278 {
279 size_t uiCount = m_aItems.Count();
280 while ( uiCount-- != 0 ) {
281 delete m_aItems[uiCount];
282 m_aItems[uiCount] = NULL;
283 }
284
285 m_aItems.Clear();
286 }
287 else
288 #endif // wxUSE_OWNER_DRAWN
289 if ( HasClientObjectData() )
290 {
291 for ( size_t n = 0; n < (size_t)m_noItems; n++ )
292 {
293 delete GetClientObject(n);
294 }
295 }
296 }
297
298 void wxListBox::DoSetSize(int x, int y,
299 int width, int height,
300 int sizeFlags )
301 {
302 wxControl::DoSetSize( x , y , width , height , sizeFlags ) ;
303 }
304
305 void wxListBox::DoSetFirstItem(int N)
306 {
307 MacScrollTo( N ) ;
308 }
309
310 void wxListBox::Delete(int N)
311 {
312 wxCHECK_RET( N >= 0 && N < m_noItems,
313 wxT("invalid index in wxListBox::Delete") );
314
315 #if wxUSE_OWNER_DRAWN
316 delete m_aItems[N];
317 m_aItems.RemoveAt(N);
318 #else // !wxUSE_OWNER_DRAWN
319 if ( HasClientObjectData() )
320 {
321 delete GetClientObject(N);
322 }
323 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
324 m_stringArray.RemoveAt( N ) ;
325 m_dataArray.RemoveAt( N ) ;
326 m_noItems --;
327
328 MacDelete( N ) ;
329 }
330
331 int wxListBox::DoAppend(const wxString& item)
332 {
333 InvalidateBestSize();
334
335 int index = m_noItems ;
336 m_stringArray.Add( item ) ;
337 m_dataArray.Add( NULL );
338 m_noItems ++;
339 DoSetItemClientData( index , NULL ) ;
340 MacAppend( item ) ;
341
342 return index ;
343 }
344
345 void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
346 {
347 Clear() ;
348 int n = choices.GetCount();
349
350 for( int i = 0 ; i < n ; ++i )
351 {
352 if ( clientData )
353 {
354 #if wxUSE_OWNER_DRAWN
355 wxASSERT_MSG(clientData[i] == NULL,
356 wxT("Can't use client data with owner-drawn listboxes"));
357 #else // !wxUSE_OWNER_DRAWN
358 Append( choices[i] , clientData[i] ) ;
359 #endif
360 }
361 else
362 Append( choices[i] ) ;
363 }
364
365 #if wxUSE_OWNER_DRAWN
366 if ( m_windowStyle & wxLB_OWNERDRAW ) {
367 // first delete old items
368 size_t ui = m_aItems.Count();
369 while ( ui-- != 0 ) {
370 delete m_aItems[ui];
371 m_aItems[ui] = NULL;
372 }
373 m_aItems.Empty();
374
375 // then create new ones
376 for ( ui = 0; ui < (size_t)m_noItems; ui++ ) {
377 wxOwnerDrawn *pNewItem = CreateItem(ui);
378 pNewItem->SetName(choices[ui]);
379 m_aItems.Add(pNewItem);
380 }
381 }
382 #endif // wxUSE_OWNER_DRAWN
383 }
384
385 int wxListBox::FindString(const wxString& s) const
386 {
387
388 if ( s.Right(1) == wxT("*") )
389 {
390 wxString search = s.Left( s.Length() - 1 ) ;
391 int len = search.Length() ;
392 Str255 s1 , s2 ;
393 wxMacStringToPascal( search , s2 ) ;
394
395 for ( int i = 0 ; i < m_noItems ; ++ i )
396 {
397 wxMacStringToPascal( m_stringArray[i].Left( len ) , s1 ) ;
398
399 if ( EqualString( s1 , s2 , false , false ) )
400 return i ;
401 }
402 if ( s.Left(1) == wxT("*") && s.Length() > 1 )
403 {
404 wxString st = s ;
405 st.MakeLower() ;
406 for ( int i = 0 ; i < m_noItems ; ++i )
407 {
408 if ( GetString(i).Lower().Matches(st) )
409 return i ;
410 }
411 }
412
413 }
414 else
415 {
416 Str255 s1 , s2 ;
417
418 wxMacStringToPascal( s , s2 ) ;
419
420 for ( int i = 0 ; i < m_noItems ; ++ i )
421 {
422 wxMacStringToPascal( m_stringArray[i] , s1 ) ;
423
424 if ( EqualString( s1 , s2 , false , false ) )
425 return i ;
426 }
427 }
428 return -1;
429 }
430
431 void wxListBox::Clear()
432 {
433 FreeData();
434 m_noItems = 0;
435 m_stringArray.Empty() ;
436 m_dataArray.Empty() ;
437 MacClear() ;
438 }
439
440 void wxListBox::SetSelection(int N, bool select)
441 {
442 if ( N == wxNOT_FOUND )
443 {
444 // unselect everything
445 int sel = MacGetSelection() ;
446 if ( sel != wxNOT_FOUND )
447 {
448 UInt32 id = sel + 1 ;
449 verify_noerr(
450 m_peer->SetSelectedItems( 1 , & id , kDataBrowserItemsRemove )
451 );
452 }
453
454 return;
455 }
456
457 wxCHECK_RET( N >= 0 && N < m_noItems,
458 wxT("invalid index in wxListBox::SetSelection") );
459 MacSetSelection( N , select ) ;
460 GetSelections( m_selectionPreImage ) ;
461 }
462
463 bool wxListBox::IsSelected(int N) const
464 {
465 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
466 wxT("invalid index in wxListBox::Selected") );
467
468 return MacIsSelected( N ) ;
469 }
470
471 void *wxListBox::DoGetItemClientData(int N) const
472 {
473 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
474 wxT("invalid index in wxListBox::GetClientData"));
475
476 return (void *)m_dataArray[N];
477 }
478
479 wxClientData *wxListBox::DoGetItemClientObject(int N) const
480 {
481 return (wxClientData *) DoGetItemClientData( N ) ;
482 }
483
484 void wxListBox::DoSetItemClientData(int N, void *Client_data)
485 {
486 wxCHECK_RET( N >= 0 && N < m_noItems,
487 wxT("invalid index in wxListBox::SetClientData") );
488
489 #if wxUSE_OWNER_DRAWN
490 if ( m_windowStyle & wxLB_OWNERDRAW )
491 {
492 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
493 // in OnMeasure/OnDraw.
494 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
495 }
496 #endif // wxUSE_OWNER_DRAWN
497 wxASSERT_MSG( m_dataArray.GetCount() >= (size_t) N , wxT("invalid client_data array") ) ;
498
499 if ( m_dataArray.GetCount() > (size_t) N )
500 {
501 m_dataArray[N] = (char*) Client_data ;
502 }
503 else
504 {
505 m_dataArray.Add( (char*) Client_data ) ;
506 }
507 }
508
509 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
510 {
511 DoSetItemClientData(n, clientData);
512 }
513
514 // Return number of selections and an array of selected integers
515 int wxListBox::GetSelections(wxArrayInt& aSelections) const
516 {
517 return MacGetSelections( aSelections ) ;
518 }
519
520 // Get single selection, for single choice list items
521 int wxListBox::GetSelection() const
522 {
523 return MacGetSelection() ;
524 }
525
526 // Find string for position
527 wxString wxListBox::GetString(int N) const
528 {
529 return m_stringArray[N] ;
530 }
531
532 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
533 {
534 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
535 wxT("invalid index in wxListBox::InsertItems") );
536
537 InvalidateBestSize();
538
539 int nItems = items.GetCount();
540
541 for ( int i = 0 ; i < nItems ; i++ )
542 {
543 m_stringArray.Insert( items[i] , pos + i ) ;
544 m_dataArray.Insert( NULL , pos + i ) ;
545 m_noItems++ ;
546 MacInsert( pos + i , items[i] ) ;
547 }
548 }
549
550 void wxListBox::SetString(int N, const wxString& s)
551 {
552 m_stringArray[N] = s ;
553 MacSet( N , s ) ;
554 }
555
556 wxSize wxListBox::DoGetBestSize() const
557 {
558 int lbWidth = 100; // some defaults
559 int lbHeight = 110;
560 int wLine;
561
562 {
563 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetTopLevelWindowRef() ) ) ;
564
565 if ( m_font.Ok() )
566 {
567 ::TextFont( m_font.MacGetFontNum() ) ;
568 ::TextSize( m_font.MacGetFontSize() ) ;
569 ::TextFace( m_font.MacGetFontStyle() ) ;
570 }
571 else
572 {
573 ::TextFont( kFontIDMonaco ) ;
574 ::TextSize( 9 );
575 ::TextFace( 0 ) ;
576 }
577
578 // Find the widest line
579 for(int i = 0; i < GetCount(); i++) {
580 wxString str(GetString(i));
581 #if wxUSE_UNICODE
582 Point bounds={0,0} ;
583 SInt16 baseline ;
584 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) ,
585 kThemeCurrentPortFont,
586 kThemeStateActive,
587 false,
588 &bounds,
589 &baseline );
590 wLine = bounds.h ;
591 #else
592 wLine = ::TextWidth( str.c_str() , 0 , str.Length() ) ;
593 #endif
594 lbWidth = wxMax(lbWidth, wLine);
595 }
596
597 // Add room for the scrollbar
598 lbWidth += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
599
600 // And just a bit more
601 int cy = 12 ;
602 int cx = ::TextWidth( "X" , 0 , 1 ) ;
603 lbWidth += cx ;
604
605 // don't make the listbox too tall (limit height to around 10 items) but don't
606 // make it too small neither
607 lbHeight = (cy+4) * wxMin(wxMax(GetCount(), 3), 10);
608 }
609
610 return wxSize(lbWidth, lbHeight);
611 }
612
613 int wxListBox::GetCount() const
614 {
615 return m_noItems;
616 }
617
618 void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
619 {
620 wxControl::Refresh( eraseBack , rect ) ;
621 // MacRedrawControl() ;
622 }
623
624 #if wxUSE_OWNER_DRAWN
625
626 class wxListBoxItem : public wxOwnerDrawn
627 {
628 public:
629 wxListBoxItem(const wxString& str = "");
630 };
631
632 wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
633 {
634 // no bitmaps/checkmarks
635 SetMarginWidth(0);
636 }
637
638 wxOwnerDrawn *wxListBox::CreateItem(size_t n)
639 {
640 return new wxListBoxItem();
641 }
642
643 #endif //USE_OWNER_DRAWN
644
645
646 // Some custom controls depend on this
647 /* static */ wxVisualAttributes
648 wxListBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
649 {
650 wxVisualAttributes attr;
651 attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
652 attr.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
653 attr.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
654 return attr;
655 }
656
657 // ============================================================================
658 // list box control implementation
659 // ============================================================================
660
661 void wxListBox::MacDelete( int N )
662 {
663 UInt32 id = m_noItems+1 ;
664 verify_noerr( m_peer->RemoveItems( kDataBrowserNoItem , 1 , (UInt32*) &id , kDataBrowserItemNoProperty ) ) ;
665 verify_noerr( m_peer->UpdateItems( kDataBrowserNoItem , 1 , (UInt32*) kDataBrowserNoItem , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ;
666 }
667
668 void wxListBox::MacInsert( int n , const wxString& text)
669 {
670 UInt32 id = m_noItems ; // this has already been increased
671 verify_noerr( m_peer->AddItems( kDataBrowserNoItem , 1 , (UInt32*) &id , kDataBrowserItemNoProperty ) ) ;
672 verify_noerr( m_peer->UpdateItems( kDataBrowserNoItem , 1 , (UInt32*) kDataBrowserNoItem , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ;
673 }
674
675 void wxListBox::MacAppend( const wxString& text)
676 {
677 UInt32 id = m_noItems ; // this has already been increased
678 verify_noerr( m_peer->AddItems( kDataBrowserNoItem , 1 , (UInt32*) &id , kDataBrowserItemNoProperty ) ) ;
679 }
680
681 void wxListBox::MacClear()
682 {
683 verify_noerr( m_peer->RemoveItems( kDataBrowserNoItem , 0 , NULL , kDataBrowserItemNoProperty ) ) ;
684 }
685
686 void wxListBox::MacSetSelection( int n , bool select )
687 {
688 UInt32 id = n + 1 ;
689 if ( !(GetWindowStyle() & (wxLB_MULTIPLE|wxLB_EXTENDED) ) )
690 {
691 int n = MacGetSelection() ;
692 if ( n >= 0 )
693 {
694 UInt32 idOld = n + 1 ;
695 m_peer->SetSelectedItems( 1 , & idOld , kDataBrowserItemsRemove ) ;
696 }
697 }
698 if ( m_peer->IsItemSelected( id ) != select )
699 {
700 verify_noerr(m_peer->SetSelectedItems( 1 , & id , kDataBrowserItemsToggle ) ) ;
701 }
702 MacScrollTo( n ) ;
703 }
704
705 bool wxListBox::MacIsSelected( int n ) const
706 {
707 return m_peer->IsItemSelected( n + 1 ) ;
708 }
709
710 int wxListBox::MacGetSelection() const
711 {
712 for ( int i = 0 ; i < GetCount() ; ++i )
713 {
714 if ( m_peer->IsItemSelected( i + 1 ) )
715 {
716 return i ;
717 }
718 }
719 return -1 ;
720 }
721
722 int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
723 {
724 int no_sel = 0 ;
725
726 aSelections.Empty();
727 for ( int i = 0 ; i < GetCount() ; ++i )
728 {
729 if ( m_peer->IsItemSelected( i + 1 ) )
730 {
731 aSelections.Add( i ) ;
732 no_sel++ ;
733 }
734 }
735 return no_sel ;
736 }
737
738 void wxListBox::MacSet( int n , const wxString& text )
739 {
740 // as we don't store the strings we only have to issue a redraw
741 UInt32 id = n + 1 ;
742 verify_noerr( m_peer->UpdateItems( kDataBrowserNoItem , 1 , &id , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ;
743 }
744
745 void wxListBox::MacScrollTo( int n )
746 {
747 UInt32 id = n + 1 ;
748 verify_noerr( m_peer->RevealItem( id , kTextColumnId , kDataBrowserRevealWithoutSelecting ) ) ;
749 }
750
751 #if !TARGET_API_MAC_OSX
752 void wxListBox::OnSize( wxSizeEvent &event)
753 {
754 }
755 #endif
756
757 void wxListBox::MacSetRedraw( bool doDraw )
758 {
759 // nothing to do in compositing mode
760 }
761
762 void wxListBox::MacDoClick()
763 {/*
764 wxArrayInt aSelections;
765 int n ;
766 size_t count = GetSelections(aSelections);
767
768 if ( count == m_selectionPreImage.GetCount() )
769 {
770 bool hasChanged = false ;
771 for ( size_t i = 0 ; i < count ; ++i )
772 {
773 if ( aSelections[i] != m_selectionPreImage[i] )
774 {
775 hasChanged = true ;
776 break ;
777 }
778 }
779 if ( !hasChanged )
780 {
781 return ;
782 }
783 }
784
785 m_selectionPreImage = aSelections;
786
787 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
788 event.SetEventObject( this );
789
790 if ( count > 0 )
791 {
792 n = aSelections[0];
793 if ( HasClientObjectData() )
794 event.SetClientObject( GetClientObject(n) );
795 else if ( HasClientUntypedData() )
796 event.SetClientData( GetClientData(n) );
797 event.SetString( GetString(n) );
798 }
799 else
800 {
801 n = -1;
802 }
803
804 event.m_commandInt = n;
805
806 GetEventHandler()->ProcessEvent(event);
807 */
808 }
809
810 void wxListBox::MacDoDoubleClick()
811 {
812 /*
813 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
814 event.SetEventObject( this );
815 GetEventHandler()->ProcessEvent(event) ;
816 */
817 }
818
819 #if !TARGET_API_MAC_OSX
820
821 void wxListBox::OnChar(wxKeyEvent& event)
822 {
823 // todo trigger proper events here
824 event.Skip() ;
825 return ;
826
827 if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER)
828 {
829 wxWindow* parent = GetParent() ;
830 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL )
831 parent = parent->GetParent() ;
832
833 if ( parent && parent->GetDefaultItem() )
834 {
835 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
836 wxButton);
837 if ( def && def->IsEnabled() )
838 {
839 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
840 event.SetEventObject(def);
841 def->Command(event);
842 return ;
843 }
844 }
845 event.Skip() ;
846 }
847 /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
848 else if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == '.' && event.MetaDown() ) )
849 {
850 // FIXME: look in ancestors, not just parent.
851 wxWindow* win = GetParent()->FindWindow( wxID_CANCEL ) ;
852 if (win)
853 {
854 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
855 new_event.SetEventObject( win );
856 win->GetEventHandler()->ProcessEvent( new_event );
857 }
858 }
859 else if ( event.GetKeyCode() == WXK_TAB )
860 {
861 wxNavigationKeyEvent new_event;
862 new_event.SetEventObject( this );
863 new_event.SetDirection( !event.ShiftDown() );
864 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
865 new_event.SetWindowChange( event.ControlDown() );
866 new_event.SetCurrentFocus( this );
867 if ( !GetEventHandler()->ProcessEvent( new_event ) )
868 event.Skip() ;
869 }
870 else if ( event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_UP )
871 {
872 // perform the default key handling first
873 wxControl::OnKeyDown( event ) ;
874
875 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
876 event.SetEventObject( this );
877
878 wxArrayInt aSelections;
879 int n, count = GetSelections(aSelections);
880 if ( count > 0 )
881 {
882 n = aSelections[0];
883 if ( HasClientObjectData() )
884 event.SetClientObject( GetClientObject(n) );
885 else if ( HasClientUntypedData() )
886 event.SetClientData( GetClientData(n) );
887 event.SetString( GetString(n) );
888 }
889 else
890 {
891 n = -1;
892 }
893
894 event.m_commandInt = n;
895
896 GetEventHandler()->ProcessEvent(event);
897 }
898 else
899 {
900 if ( event.GetTimestamp() > m_lastTypeIn + 60 )
901 {
902 m_typeIn = wxEmptyString ;
903 }
904 m_lastTypeIn = event.GetTimestamp() ;
905 m_typeIn += (char) event.GetKeyCode() ;
906 int line = FindString(wxT("*")+m_typeIn+wxT("*")) ;
907 if ( line >= 0 )
908 {
909 if ( GetSelection() != line )
910 {
911 SetSelection(line) ;
912 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
913 event.SetEventObject( this );
914
915 if ( HasClientObjectData() )
916 event.SetClientObject( GetClientObject( line ) );
917 else if ( HasClientUntypedData() )
918 event.SetClientData( GetClientData(line) );
919 event.SetString( GetString(line) );
920
921 event.m_commandInt = line ;
922
923 GetEventHandler()->ProcessEvent(event);
924 }
925 }
926 }
927 }
928
929 #endif
930