]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listbox.cpp
[ 1035247 ] fix the number of ticks in slider (with annotations)
[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 #if !__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 wxCHECK_RET( N >= 0 && N < m_noItems,
443 wxT("invalid index in wxListBox::SetSelection") );
444 MacSetSelection( N , select ) ;
445 GetSelections( m_selectionPreImage ) ;
446 }
447
448 bool wxListBox::IsSelected(int N) const
449 {
450 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
451 wxT("invalid index in wxListBox::Selected") );
452
453 return MacIsSelected( N ) ;
454 }
455
456 void *wxListBox::DoGetItemClientData(int N) const
457 {
458 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
459 wxT("invalid index in wxListBox::GetClientData"));
460
461 return (void *)m_dataArray[N];
462 }
463
464 wxClientData *wxListBox::DoGetItemClientObject(int N) const
465 {
466 return (wxClientData *) DoGetItemClientData( N ) ;
467 }
468
469 void wxListBox::DoSetItemClientData(int N, void *Client_data)
470 {
471 wxCHECK_RET( N >= 0 && N < m_noItems,
472 wxT("invalid index in wxListBox::SetClientData") );
473
474 #if wxUSE_OWNER_DRAWN
475 if ( m_windowStyle & wxLB_OWNERDRAW )
476 {
477 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
478 // in OnMeasure/OnDraw.
479 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
480 }
481 #endif // wxUSE_OWNER_DRAWN
482 wxASSERT_MSG( m_dataArray.GetCount() >= (size_t) N , wxT("invalid client_data array") ) ;
483
484 if ( m_dataArray.GetCount() > (size_t) N )
485 {
486 m_dataArray[N] = (char*) Client_data ;
487 }
488 else
489 {
490 m_dataArray.Add( (char*) Client_data ) ;
491 }
492 }
493
494 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
495 {
496 DoSetItemClientData(n, clientData);
497 }
498
499 // Return number of selections and an array of selected integers
500 int wxListBox::GetSelections(wxArrayInt& aSelections) const
501 {
502 return MacGetSelections( aSelections ) ;
503 }
504
505 // Get single selection, for single choice list items
506 int wxListBox::GetSelection() const
507 {
508 return MacGetSelection() ;
509 }
510
511 // Find string for position
512 wxString wxListBox::GetString(int N) const
513 {
514 return m_stringArray[N] ;
515 }
516
517 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
518 {
519 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
520 wxT("invalid index in wxListBox::InsertItems") );
521
522 InvalidateBestSize();
523
524 int nItems = items.GetCount();
525
526 for ( int i = 0 ; i < nItems ; i++ )
527 {
528 m_stringArray.Insert( items[i] , pos + i ) ;
529 m_dataArray.Insert( NULL , pos + i ) ;
530 m_noItems++ ;
531 MacInsert( pos + i , items[i] ) ;
532 }
533 }
534
535 void wxListBox::SetString(int N, const wxString& s)
536 {
537 m_stringArray[N] = s ;
538 MacSet( N , s ) ;
539 }
540
541 wxSize wxListBox::DoGetBestSize() const
542 {
543 int lbWidth = 100; // some defaults
544 int lbHeight = 110;
545 int wLine;
546
547 {
548 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetTopLevelWindowRef() ) ) ;
549
550 if ( m_font.Ok() )
551 {
552 ::TextFont( m_font.MacGetFontNum() ) ;
553 ::TextSize( m_font.MacGetFontSize() ) ;
554 ::TextFace( m_font.MacGetFontStyle() ) ;
555 }
556 else
557 {
558 ::TextFont( kFontIDMonaco ) ;
559 ::TextSize( 9 );
560 ::TextFace( 0 ) ;
561 }
562
563 // Find the widest line
564 for(int i = 0; i < GetCount(); i++) {
565 wxString str(GetString(i));
566 #if wxUSE_UNICODE
567 Point bounds={0,0} ;
568 SInt16 baseline ;
569 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) ,
570 kThemeCurrentPortFont,
571 kThemeStateActive,
572 false,
573 &bounds,
574 &baseline );
575 wLine = bounds.h ;
576 #else
577 wLine = ::TextWidth( str.c_str() , 0 , str.Length() ) ;
578 #endif
579 lbWidth = wxMax(lbWidth, wLine);
580 }
581
582 // Add room for the scrollbar
583 lbWidth += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
584
585 // And just a bit more
586 int cy = 12 ;
587 int cx = ::TextWidth( "X" , 0 , 1 ) ;
588 lbWidth += cx ;
589
590 // don't make the listbox too tall (limit height to around 10 items) but don't
591 // make it too small neither
592 lbHeight = (cy+4) * wxMin(wxMax(GetCount(), 3), 10);
593 }
594
595 return wxSize(lbWidth, lbHeight);
596 }
597
598 int wxListBox::GetCount() const
599 {
600 return m_noItems;
601 }
602
603 void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
604 {
605 wxControl::Refresh( eraseBack , rect ) ;
606 // MacRedrawControl() ;
607 }
608
609 #if wxUSE_OWNER_DRAWN
610
611 class wxListBoxItem : public wxOwnerDrawn
612 {
613 public:
614 wxListBoxItem(const wxString& str = "");
615 };
616
617 wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
618 {
619 // no bitmaps/checkmarks
620 SetMarginWidth(0);
621 }
622
623 wxOwnerDrawn *wxListBox::CreateItem(size_t n)
624 {
625 return new wxListBoxItem();
626 }
627
628 #endif //USE_OWNER_DRAWN
629
630
631 // Some custom controls depend on this
632 /* static */ wxVisualAttributes
633 wxListBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
634 {
635 wxVisualAttributes attr;
636 attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
637 attr.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
638 attr.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
639 return attr;
640 }
641
642 // ============================================================================
643 // list box control implementation
644 // ============================================================================
645
646 void wxListBox::MacDelete( int N )
647 {
648 UInt32 id = m_noItems+1 ;
649 verify_noerr( m_peer->RemoveItems( kDataBrowserNoItem , 1 , (UInt32*) &id , kDataBrowserItemNoProperty ) ) ;
650 verify_noerr( m_peer->UpdateItems( kDataBrowserNoItem , 1 , (UInt32*) kDataBrowserNoItem , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ;
651 }
652
653 void wxListBox::MacInsert( int n , const wxString& text)
654 {
655 UInt32 id = m_noItems ; // this has already been increased
656 verify_noerr( m_peer->AddItems( kDataBrowserNoItem , 1 , (UInt32*) &id , kDataBrowserItemNoProperty ) ) ;
657 verify_noerr( m_peer->UpdateItems( kDataBrowserNoItem , 1 , (UInt32*) kDataBrowserNoItem , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ;
658 }
659
660 void wxListBox::MacAppend( const wxString& text)
661 {
662 UInt32 id = m_noItems ; // this has already been increased
663 verify_noerr( m_peer->AddItems( kDataBrowserNoItem , 1 , (UInt32*) &id , kDataBrowserItemNoProperty ) ) ;
664 }
665
666 void wxListBox::MacClear()
667 {
668 verify_noerr( m_peer->RemoveItems( kDataBrowserNoItem , 0 , NULL , kDataBrowserItemNoProperty ) ) ;
669 }
670
671 void wxListBox::MacSetSelection( int n , bool select )
672 {
673 UInt32 id = n + 1 ;
674 if ( !(GetWindowStyle() & (wxLB_MULTIPLE|wxLB_EXTENDED) ) )
675 {
676 int n = MacGetSelection() ;
677 if ( n >= 0 )
678 {
679 UInt32 idOld = n + 1 ;
680 m_peer->SetSelectedItems( 1 , & idOld , kDataBrowserItemsRemove ) ;
681 }
682 }
683 if ( m_peer->IsItemSelected( id ) != select )
684 {
685 verify_noerr(m_peer->SetSelectedItems( 1 , & id , kDataBrowserItemsToggle ) ) ;
686 }
687 MacScrollTo( n ) ;
688 }
689
690 bool wxListBox::MacIsSelected( int n ) const
691 {
692 return m_peer->IsItemSelected( n + 1 ) ;
693 }
694
695 int wxListBox::MacGetSelection() const
696 {
697 for ( int i = 0 ; i < GetCount() ; ++i )
698 {
699 if ( m_peer->IsItemSelected( i + 1 ) )
700 {
701 return i ;
702 }
703 }
704 return -1 ;
705 }
706
707 int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
708 {
709 int no_sel = 0 ;
710
711 aSelections.Empty();
712 for ( int i = 0 ; i < GetCount() ; ++i )
713 {
714 if ( m_peer->IsItemSelected( i + 1 ) )
715 {
716 aSelections.Add( i ) ;
717 no_sel++ ;
718 }
719 }
720 return no_sel ;
721 }
722
723 void wxListBox::MacSet( int n , const wxString& text )
724 {
725 // as we don't store the strings we only have to issue a redraw
726 UInt32 id = n + 1 ;
727 verify_noerr( m_peer->UpdateItems( kDataBrowserNoItem , 1 , &id , kDataBrowserItemNoProperty , kDataBrowserItemNoProperty ) ) ;
728 }
729
730 void wxListBox::MacScrollTo( int n )
731 {
732 UInt32 id = n + 1 ;
733 verify_noerr( m_peer->RevealItem( id , kTextColumnId , kDataBrowserRevealWithoutSelecting ) ) ;
734 }
735
736 #if !TARGET_API_MAC_OSX
737 void wxListBox::OnSize( wxSizeEvent &event)
738 {
739 }
740 #endif
741
742 void wxListBox::MacSetRedraw( bool doDraw )
743 {
744 // nothing to do in compositing mode
745 }
746
747 void wxListBox::MacDoClick()
748 {/*
749 wxArrayInt aSelections;
750 int n ;
751 size_t count = GetSelections(aSelections);
752
753 if ( count == m_selectionPreImage.GetCount() )
754 {
755 bool hasChanged = false ;
756 for ( size_t i = 0 ; i < count ; ++i )
757 {
758 if ( aSelections[i] != m_selectionPreImage[i] )
759 {
760 hasChanged = true ;
761 break ;
762 }
763 }
764 if ( !hasChanged )
765 {
766 return ;
767 }
768 }
769
770 m_selectionPreImage = aSelections;
771
772 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
773 event.SetEventObject( this );
774
775 if ( count > 0 )
776 {
777 n = aSelections[0];
778 if ( HasClientObjectData() )
779 event.SetClientObject( GetClientObject(n) );
780 else if ( HasClientUntypedData() )
781 event.SetClientData( GetClientData(n) );
782 event.SetString( GetString(n) );
783 }
784 else
785 {
786 n = -1;
787 }
788
789 event.m_commandInt = n;
790
791 GetEventHandler()->ProcessEvent(event);
792 */
793 }
794
795 void wxListBox::MacDoDoubleClick()
796 {
797 /*
798 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
799 event.SetEventObject( this );
800 GetEventHandler()->ProcessEvent(event) ;
801 */
802 }
803
804 #if !TARGET_API_MAC_OSX
805
806 void wxListBox::OnChar(wxKeyEvent& event)
807 {
808 // todo trigger proper events here
809 event.Skip() ;
810 return ;
811
812 if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER)
813 {
814 wxWindow* parent = GetParent() ;
815 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL )
816 parent = parent->GetParent() ;
817
818 if ( parent && parent->GetDefaultItem() )
819 {
820 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
821 wxButton);
822 if ( def && def->IsEnabled() )
823 {
824 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
825 event.SetEventObject(def);
826 def->Command(event);
827 return ;
828 }
829 }
830 event.Skip() ;
831 }
832 /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
833 else if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == '.' && event.MetaDown() ) )
834 {
835 // FIXME: look in ancestors, not just parent.
836 wxWindow* win = GetParent()->FindWindow( wxID_CANCEL ) ;
837 if (win)
838 {
839 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
840 new_event.SetEventObject( win );
841 win->GetEventHandler()->ProcessEvent( new_event );
842 }
843 }
844 else if ( event.GetKeyCode() == WXK_TAB )
845 {
846 wxNavigationKeyEvent new_event;
847 new_event.SetEventObject( this );
848 new_event.SetDirection( !event.ShiftDown() );
849 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
850 new_event.SetWindowChange( event.ControlDown() );
851 new_event.SetCurrentFocus( this );
852 if ( !GetEventHandler()->ProcessEvent( new_event ) )
853 event.Skip() ;
854 }
855 else if ( event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_UP )
856 {
857 // perform the default key handling first
858 wxControl::OnKeyDown( event ) ;
859
860 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
861 event.SetEventObject( this );
862
863 wxArrayInt aSelections;
864 int n, count = GetSelections(aSelections);
865 if ( count > 0 )
866 {
867 n = aSelections[0];
868 if ( HasClientObjectData() )
869 event.SetClientObject( GetClientObject(n) );
870 else if ( HasClientUntypedData() )
871 event.SetClientData( GetClientData(n) );
872 event.SetString( GetString(n) );
873 }
874 else
875 {
876 n = -1;
877 }
878
879 event.m_commandInt = n;
880
881 GetEventHandler()->ProcessEvent(event);
882 }
883 else
884 {
885 if ( event.GetTimestamp() > m_lastTypeIn + 60 )
886 {
887 m_typeIn = wxEmptyString ;
888 }
889 m_lastTypeIn = event.GetTimestamp() ;
890 m_typeIn += (char) event.GetKeyCode() ;
891 int line = FindString(wxT("*")+m_typeIn+wxT("*")) ;
892 if ( line >= 0 )
893 {
894 if ( GetSelection() != line )
895 {
896 SetSelection(line) ;
897 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
898 event.SetEventObject( this );
899
900 if ( HasClientObjectData() )
901 event.SetClientObject( GetClientObject( line ) );
902 else if ( HasClientUntypedData() )
903 event.SetClientData( GetClientData(line) );
904 event.SetString( GetString(line) );
905
906 event.m_commandInt = line ;
907
908 GetEventHandler()->ProcessEvent(event);
909 }
910 }
911 }
912 }
913
914 #endif
915