]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/listbox.cpp
Fixed bug that was giving the wrong size of wxCustomDataObjects to the receiver.
[wxWidgets.git] / src / mac / carbon / listbox.cpp
CommitLineData
e9576ca5
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: listbox.cpp
3// Purpose: wxListBox
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "listbox.h"
14#endif
15
16#include "wx/listbox.h"
17#include "wx/settings.h"
18#include "wx/dynarray.h"
19#include "wx/log.h"
20
519cb848
SC
21#include "wx/utils.h"
22#include "extldef.h"
23
2f1ae414 24#if !USE_SHARED_LIBRARY
e9576ca5 25 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
519cb848
SC
26
27BEGIN_EVENT_TABLE(wxListBox, wxControl)
28 EVT_SIZE( wxListBox::OnSize )
29END_EVENT_TABLE()
2f1ae414 30#endif
e9576ca5 31
519cb848
SC
32#include <wx/mac/uma.h>
33
34extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
35const short kwxMacListWithVerticalScrollbar = 128 ;
36
e9576ca5
SC
37// ============================================================================
38// list box control implementation
39// ============================================================================
40
41// Listbox item
42wxListBox::wxListBox()
43{
44 m_noItems = 0;
45 m_selected = 0;
2f1ae414 46 m_macList = NULL ;
e9576ca5
SC
47}
48
49bool wxListBox::Create(wxWindow *parent, wxWindowID id,
50 const wxPoint& pos,
51 const wxSize& size,
52 int n, const wxString choices[],
53 long style,
54 const wxValidator& validator,
55 const wxString& name)
56{
519cb848 57 m_noItems = 0 ; // this will be increased by our append command
e9576ca5
SC
58 m_selected = 0;
59
519cb848
SC
60 Rect bounds ;
61 Str255 title ;
519cb848
SC
62
63 MacPreControlCreate( parent , id , "" , pos , size ,style, validator , name , &bounds , title ) ;
64
65 m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , title , true , kwxMacListWithVerticalScrollbar , 0 , 0,
66 kControlListBoxProc , (long) this ) ;
67
68 long result ;
69 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxListHandleTag , sizeof( ListHandle ) , (char*) &m_macList , &result ) ;
70
2f1ae414 71 HLock( (Handle) m_macList ) ;
519cb848 72 NewExtLDEFInfo( m_macList , MacDrawStringCell , (long) this ) ;
8208e181
SC
73 (**m_macList).selFlags = 0 ;
74 if ( style & wxLB_MULTIPLE )
519cb848
SC
75 {
76 (**m_macList).selFlags += lNoExtend ;
77 }
78 else if ( style & wxLB_EXTENDED )
79 {
80 (**m_macList).selFlags += lExtendDrag ;
81 }
8208e181
SC
82 else
83 {
84 (**m_macList).selFlags = lOnlyOne ;
85 }
519cb848
SC
86 Point pt = (**m_macList).cellSize ;
87 pt.v = 14 ;
88 LCellSize( pt , m_macList ) ;
89
90 LAddColumn( 1 , 0 , m_macList ) ;
91
92 MacPostControlCreate() ;
93
94 ControlFontStyleRec controlstyle ;
95 controlstyle.flags = kControlUseFontMask + kControlUseSizeMask ;
96 //controlstyle.font = kControlFontSmallSystemFont ;
97 controlstyle.font = kFontIDMonaco ;
98 controlstyle.size = 9 ;
99 ::UMASetControlFontStyle( m_macControl , &controlstyle ) ;
100
101 for ( int i = 0 ; i < n ; i++ )
102 {
103 Append( choices[i] ) ;
104 }
105
106 LSetDrawingMode( true , m_macList ) ;
107
108 return TRUE;
e9576ca5
SC
109}
110
111wxListBox::~wxListBox()
112{
e7549107 113 Free() ;
2f1ae414
SC
114 if ( m_macList )
115 {
116 DisposeExtLDEFInfo( m_macList ) ;
117 m_macList = NULL ;
118 }
e9576ca5
SC
119}
120
e7549107 121void wxListBox::Free()
e9576ca5 122{
e7549107
SC
123#if wxUSE_OWNER_DRAWN
124 if ( m_windowStyle & wxLB_OWNERDRAW )
125 {
126 size_t uiCount = m_aItems.Count();
127 while ( uiCount-- != 0 ) {
128 delete m_aItems[uiCount];
129 }
130
131 m_aItems.Clear();
132 }
133 else
134#endif // wxUSE_OWNER_DRAWN
135 if ( HasClientObjectData() )
136 {
137 for ( size_t n = 0; n < (size_t)m_noItems; n++ )
138 {
139 delete GetClientObject(n);
140 }
141 }
e9576ca5
SC
142}
143
e7549107 144void wxListBox::DoSetFirstItem(int N)
e9576ca5 145{
e7549107 146 MacScrollTo( N ) ;
e9576ca5
SC
147}
148
149void wxListBox::Delete(int N)
150{
e7549107
SC
151 wxCHECK_RET( N >= 0 && N < m_noItems,
152 wxT("invalid index in wxListBox::Delete") );
153
154#if wxUSE_OWNER_DRAWN
155 delete m_aItems[N];
156 m_aItems.Remove(N);
157#else // !wxUSE_OWNER_DRAWN
158 if ( HasClientObjectData() )
159 {
160 delete GetClientObject(N);
161 }
162#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
519cb848 163 m_stringArray.Remove( N ) ;
8208e181 164 m_dataArray.Remove( N ) ;
2f1ae414 165 m_noItems --;
519cb848
SC
166
167 MacDelete( N ) ;
e9576ca5
SC
168}
169
e7549107 170int wxListBox::DoAppend(const wxString& item)
e9576ca5 171{
e7549107 172 int index = m_noItems ;
519cb848
SC
173 if( wxApp::s_macDefaultEncodingIsPC )
174 {
175 m_stringArray.Add( wxMacMakeMacStringFromPC( item ) ) ;
b81abd0d 176 m_dataArray.Add( NULL );
519cb848 177 }
b81abd0d 178 else {
519cb848 179 m_stringArray.Add( item ) ;
b81abd0d
GD
180 m_dataArray.Add( NULL );
181 }
e7549107 182 m_noItems ++;
5b781a67 183 DoSetItemClientData( index , NULL ) ;
519cb848 184 MacAppend( item ) ;
e7549107 185
e7549107 186 return index ;
e9576ca5
SC
187}
188
e7549107
SC
189void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
190{
191 MacSetRedraw( false ) ;
519cb848 192 Clear() ;
e7549107
SC
193 int n = choices.GetCount();
194
519cb848
SC
195 for( int i = 0 ; i < n ; ++i )
196 {
197 if ( clientData )
e7549107
SC
198 {
199#if wxUSE_OWNER_DRAWN
200 wxASSERT_MSG(clientData[i] == NULL,
201 wxT("Can't use client data with owner-drawn listboxes"));
202#else // !wxUSE_OWNER_DRAWN
8208e181 203 Append( choices[i] , clientData[i] ) ;
e7549107
SC
204 #endif
205 }
519cb848
SC
206 else
207 Append( choices[i] ) ;
208 }
e7549107
SC
209
210#if wxUSE_OWNER_DRAWN
211 if ( m_windowStyle & wxLB_OWNERDRAW ) {
212 // first delete old items
213 size_t ui = m_aItems.Count();
214 while ( ui-- != 0 ) {
215 delete m_aItems[ui];
216 }
217 m_aItems.Empty();
218
219 // then create new ones
220 for ( ui = 0; ui < (size_t)m_noItems; ui++ ) {
221 wxOwnerDrawn *pNewItem = CreateItem(ui);
222 pNewItem->SetName(choices[ui]);
223 m_aItems.Add(pNewItem);
224 }
225 }
226#endif // wxUSE_OWNER_DRAWN
227 MacSetRedraw( true ) ;
228}
229
230bool wxListBox::HasMultipleSelection() const
231{
232 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
e9576ca5
SC
233}
234
519cb848 235int wxListBox::FindString(const wxString& st) const
e9576ca5 236{
519cb848
SC
237 wxString s ;
238 if( wxApp::s_macDefaultEncodingIsPC )
239 {
240 s = wxMacMakeMacStringFromPC( st ) ;
241 }
242 else
243 s = st ;
244
245 if ( s.Right(1) == "*" )
246 {
247 wxString search = s.Left( s.Length() - 1 ) ;
248 int len = search.Length() ;
2f1ae414
SC
249 Str255 s1 , s2 ;
250 strcpy( (char*) s2 , search.c_str() ) ;
251 c2pstr( (char*) s2 ) ;
252 for ( int i = 0 ; i < m_noItems ; ++ i )
253 {
254 strcpy( (char*) s1 , m_stringArray[i].Left( len ).c_str() ) ;
255 c2pstr( (char*) s1 ) ;
256 if ( EqualString( s1 , s2 , false , false ) )
257 return i ;
258 }
5b781a67
SC
259 if ( s.Left(1) = "*" && s.Length() > 1 )
260 {
261 s.MakeLower() ;
262 for ( int i = 0 ; i < m_noItems ; ++i )
263 {
264 if ( GetString(i).Lower().Matches(s) )
265 return i ;
266 }
267 }
268
519cb848
SC
269 }
270 else
271 {
2f1ae414
SC
272 Str255 s1 , s2 ;
273 strcpy( (char*) s2 , s.c_str() ) ;
274 c2pstr( (char*) s2 ) ;
275 for ( int i = 0 ; i < m_noItems ; ++ i )
276 {
277 strcpy( (char*) s1 , m_stringArray[i].c_str() ) ;
278 c2pstr( (char*) s1 ) ;
279 if ( EqualString( s1 , s2 , false , false ) )
280 return i ;
281 }
519cb848
SC
282 }
283 return -1;
e9576ca5
SC
284}
285
286void wxListBox::Clear()
287{
e7549107 288 Free();
e9576ca5 289 m_noItems = 0;
519cb848
SC
290 m_stringArray.Empty() ;
291 m_dataArray.Empty() ;
292 MacClear() ;
e9576ca5
SC
293}
294
295void wxListBox::SetSelection(int N, bool select)
296{
519cb848
SC
297 wxCHECK_RET( N >= 0 && N < m_noItems,
298 "invalid index in wxListBox::SetSelection" );
299 MacSetSelection( N , select ) ;
e9576ca5
SC
300}
301
e7549107 302bool wxListBox::IsSelected(int N) const
e9576ca5 303{
519cb848
SC
304 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
305 "invalid index in wxListBox::Selected" );
306
307 return MacIsSelected( N ) ;
e9576ca5
SC
308}
309
e7549107 310void *wxListBox::DoGetItemClientData(int N) const
e9576ca5 311{
519cb848
SC
312 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
313 "invalid index in wxListBox::GetClientData" );
314
e7549107 315 return (void *)m_dataArray[N];
e9576ca5
SC
316}
317
51abe921
SC
318wxClientData *wxListBox::DoGetItemClientObject(int N) const
319{
320 return (wxClientData *) DoGetItemClientData( N ) ;
321}
322
e7549107 323void wxListBox::DoSetItemClientData(int N, void *Client_data)
e9576ca5 324{
519cb848
SC
325 wxCHECK_RET( N >= 0 && N < m_noItems,
326 "invalid index in wxListBox::SetClientData" );
327
e7549107
SC
328#if wxUSE_OWNER_DRAWN
329 if ( m_windowStyle & wxLB_OWNERDRAW )
330 {
331 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
332 // in OnMeasure/OnDraw.
333 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
334 }
335#endif // wxUSE_OWNER_DRAWN
8208e181
SC
336 wxASSERT_MSG( m_dataArray.GetCount() >= N , "invalid client_data array" ) ;
337
338 if ( m_dataArray.GetCount() > N )
339 {
340 m_dataArray[N] = (char*) Client_data ;
2f1ae414 341 }
8208e181
SC
342 else
343 {
344 m_dataArray.Add( (char*) Client_data ) ;
345 }
e7549107
SC
346}
347
348void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
349{
350 DoSetItemClientData(n, clientData);
e9576ca5
SC
351}
352
353// Return number of selections and an array of selected integers
354int wxListBox::GetSelections(wxArrayInt& aSelections) const
355{
519cb848 356 return MacGetSelections( aSelections ) ;
e9576ca5
SC
357
358/* TODO
519cb848 359 if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED))
e9576ca5
SC
360 {
361 int no_sel = ??
362 for ( int n = 0; n < no_sel; n++ )
363 aSelections.Add(??);
364
365 return no_sel;
366 }
367 else // single-selection listbox
368 {
369 aSelections.Add(??);
370
371 return 1;
372 }
373*/
e9576ca5
SC
374}
375
376// Get single selection, for single choice list items
377int wxListBox::GetSelection() const
378{
519cb848 379 return MacGetSelection() ;
e9576ca5
SC
380}
381
382// Find string for position
383wxString wxListBox::GetString(int N) const
384{
519cb848
SC
385 if( wxApp::s_macDefaultEncodingIsPC )
386 {
387 return wxMacMakePCStringFromMac( m_stringArray[N] ) ;
388 }
389 else
390 return m_stringArray[N] ;
e9576ca5
SC
391}
392
e7549107 393void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
e9576ca5 394{
e7549107
SC
395 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
396 wxT("invalid index in wxListBox::InsertItems") );
397
398 int nItems = items.GetCount();
399
519cb848
SC
400 for ( int i = 0 ; i < nItems ; i++ )
401 {
402 m_stringArray.Insert( items[i] , pos + i ) ;
403 m_dataArray.Insert( NULL , pos + i ) ;
404 MacInsert( pos + i , items[i] ) ;
405 }
e9576ca5 406
519cb848 407 m_noItems += nItems;
e9576ca5
SC
408}
409
410void wxListBox::SetString(int N, const wxString& s)
411{
2f1ae414
SC
412 wxString str ;
413 if( wxApp::s_macDefaultEncodingIsPC )
414 {
415 str = wxMacMakeMacStringFromPC( s ) ;
416 }
417 else
418 str = s ;
419 m_stringArray[N] = str ;
519cb848 420 MacSet( N , s ) ;
e9576ca5
SC
421}
422
37e2cb08 423wxSize wxListBox::DoGetBestSize() const
e9576ca5 424{
e7549107 425 return wxSize(100, 100);
e9576ca5
SC
426}
427
51abe921
SC
428int wxListBox::GetCount() const
429{
430 return m_noItems;
431}
432
433void wxListBox::SetupColours()
434{
435 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
436 SetForegroundColour(GetParent()->GetForegroundColour());
437}
438
439#if wxUSE_OWNER_DRAWN
440
441class wxListBoxItem : public wxOwnerDrawn
442{
443public:
444 wxListBoxItem(const wxString& str = "");
445};
446
447wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
448{
449 // no bitmaps/checkmarks
450 SetMarginWidth(0);
451}
452
453wxOwnerDrawn *wxListBox::CreateItem(size_t n)
454{
455 return new wxListBoxItem();
456}
457
458#endif //USE_OWNER_DRAWN
e9576ca5 459
519cb848
SC
460// ============================================================================
461// list box control implementation
462// ============================================================================
463
464void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon)
465{
466 wxListBox* list;
467 // typecast our refCon
468 list = (wxListBox*)refCon;
469
470 MoveTo(cellRect->left + 4 , cellRect->top + 10 );
471 const wxString text = list->m_stringArray[lCell.v] ;
472 ::TextFont( kFontIDMonaco ) ;
473 ::TextSize( 9 );
474 ::TextFace( 0 ) ;
475 DrawText(text, 0 , text.Length());
476
477}
478
479void wxListBox::MacDelete( int N )
480{
481 ListHandle list ;
482 long result ;
483 Cell cell = { 0 , 0 } ;
484 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxListHandleTag , sizeof( ListHandle ) , (char*) &list , &result ) ;
485 LDelRow( 1 , N , list ) ;
486}
487
488void wxListBox::MacInsert( int n , const char * text)
489{
490 Cell cell ;
491
492 cell.h = 0 ;
493 cell.v = n ;
494
495 LAddRow( 1 , cell.v , m_macList ) ;
496}
497
498void wxListBox::MacAppend( const char * text)
499{
500 Cell cell = { 0 , 0 } ;
501 cell.v = (**m_macList).dataBounds.bottom ;
502 LAddRow( 1 , cell.v , m_macList ) ;
503}
504
505void wxListBox::MacClear()
506{
507 LDelRow( (**m_macList).dataBounds.bottom , 0 , m_macList ) ;
508}
509
510void wxListBox::MacSetSelection( int n , bool select )
511{
512 Cell cell = { 0 , 0 } ;
513 if ( LGetSelect( TRUE , &cell , m_macList ) )
514 {
515 LSetSelect( false , cell , m_macList ) ;
516 }
517
518 cell.v = n ;
519 LSetSelect( select , cell , m_macList ) ;
520 LAutoScroll( m_macList ) ;
521}
522
523bool wxListBox::MacIsSelected( int n ) const
524{
525 Cell cell = { 0 , 0 } ;
526 cell.v = n ;
527 return LGetSelect( false , &cell , m_macList ) ;
528}
529
530void wxListBox::MacDestroy()
531{
532// DisposeExtLDEFInfo( m_macList ) ;
533}
534
535int wxListBox::MacGetSelection() const
536{
537 Cell cell = { 0 , 0 } ;
538 if ( LGetSelect( true , &cell , m_macList ) )
539 return cell.v ;
540 else
541 return -1 ;
542}
543
544int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
545{
546 int no_sel = 0 ;
547
548 aSelections.Empty();
549
550 Cell cell = { 0 , 0 } ;
551 cell.v = 0 ;
552
553 while ( LGetSelect( true , &cell , m_macList ) )
554 {
555 aSelections.Add( cell.v ) ;
556 no_sel++ ;
557 cell.v++ ;
558 }
559 return no_sel ;
560}
561
562void wxListBox::MacSet( int n , const char * text )
563{
564 // our implementation does not store anything in the list
565 // so we just have to redraw
566 Cell cell = { 0 , 0 } ;
567 cell.v = n ;
568 LDraw( cell , m_macList ) ;
569}
570
571void wxListBox::MacScrollTo( int n )
572{
573 // TODO implement scrolling
574}
575
576void wxListBox::OnSize( const wxSizeEvent &event)
577{
578 Point pt = (**m_macList).cellSize ;
2f1ae414 579 pt.h = m_width - 15 ;
519cb848
SC
580 LCellSize( pt , m_macList ) ;
581}
582
583void wxListBox::MacHandleControlClick( ControlHandle control , SInt16 controlpart )
584{
585 Boolean wasDoubleClick = false ;
586 long result ;
587
588 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxDoubleClickTag , sizeof( wasDoubleClick ) , (char*) &wasDoubleClick , &result ) ;
589 if ( !wasDoubleClick )
590 {
591 MacDoClick() ;
592 }
593 else
594 {
595 MacDoDoubleClick() ;
596 }
597}
598
599void wxListBox::MacSetRedraw( bool doDraw )
600{
601 LSetDrawingMode( doDraw , m_macList ) ;
602
603}
604
605void wxListBox::MacDoClick()
606{
607 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
e7549107
SC
608 event.SetEventObject( this );
609
519cb848 610 wxArrayInt aSelections;
e7549107 611 int n, count = GetSelections(aSelections);
519cb848
SC
612 if ( count > 0 )
613 {
7c74e7fe
SC
614 n = aSelections[0];
615 if ( HasClientObjectData() )
e7549107
SC
616 event.SetClientObject( GetClientObject(n) );
617 else if ( HasClientUntypedData() )
618 event.SetClientData( GetClientData(n) );
619 event.SetString( GetString(n) );
519cb848
SC
620 }
621 else
622 {
e7549107 623 n = -1;
519cb848
SC
624 }
625
e7549107
SC
626 event.m_commandInt = n;
627
628 GetEventHandler()->ProcessEvent(event);
519cb848
SC
629}
630
631void wxListBox::MacDoDoubleClick()
632{
633 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
634 event.SetEventObject( this );
635 GetEventHandler()->ProcessEvent(event) ;
636}