]> git.saurik.com Git - wxWidgets.git/blame - src/mac/listbox.cpp
applied wxNativeFontInfo patch from Derry Bryson (with minor changes)
[wxWidgets.git] / src / mac / 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 ) ) ;
176 }
177 else
178 m_stringArray.Add( item ) ;
e7549107 179 m_noItems ++;
519cb848 180 MacAppend( item ) ;
e7549107 181
e7549107 182 return index ;
e9576ca5
SC
183}
184
e7549107
SC
185void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
186{
187 MacSetRedraw( false ) ;
519cb848 188 Clear() ;
e7549107
SC
189 int n = choices.GetCount();
190
519cb848
SC
191 for( int i = 0 ; i < n ; ++i )
192 {
193 if ( clientData )
e7549107
SC
194 {
195#if wxUSE_OWNER_DRAWN
196 wxASSERT_MSG(clientData[i] == NULL,
197 wxT("Can't use client data with owner-drawn listboxes"));
198#else // !wxUSE_OWNER_DRAWN
8208e181 199 Append( choices[i] , clientData[i] ) ;
e7549107
SC
200 #endif
201 }
519cb848
SC
202 else
203 Append( choices[i] ) ;
204 }
e7549107
SC
205
206#if wxUSE_OWNER_DRAWN
207 if ( m_windowStyle & wxLB_OWNERDRAW ) {
208 // first delete old items
209 size_t ui = m_aItems.Count();
210 while ( ui-- != 0 ) {
211 delete m_aItems[ui];
212 }
213 m_aItems.Empty();
214
215 // then create new ones
216 for ( ui = 0; ui < (size_t)m_noItems; ui++ ) {
217 wxOwnerDrawn *pNewItem = CreateItem(ui);
218 pNewItem->SetName(choices[ui]);
219 m_aItems.Add(pNewItem);
220 }
221 }
222#endif // wxUSE_OWNER_DRAWN
223 MacSetRedraw( true ) ;
224}
225
226bool wxListBox::HasMultipleSelection() const
227{
228 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
e9576ca5
SC
229}
230
519cb848 231int wxListBox::FindString(const wxString& st) const
e9576ca5 232{
519cb848
SC
233 wxString s ;
234 if( wxApp::s_macDefaultEncodingIsPC )
235 {
236 s = wxMacMakeMacStringFromPC( st ) ;
237 }
238 else
239 s = st ;
240
241 if ( s.Right(1) == "*" )
242 {
243 wxString search = s.Left( s.Length() - 1 ) ;
244 int len = search.Length() ;
2f1ae414
SC
245 Str255 s1 , s2 ;
246 strcpy( (char*) s2 , search.c_str() ) ;
247 c2pstr( (char*) s2 ) ;
248 for ( int i = 0 ; i < m_noItems ; ++ i )
249 {
250 strcpy( (char*) s1 , m_stringArray[i].Left( len ).c_str() ) ;
251 c2pstr( (char*) s1 ) ;
252 if ( EqualString( s1 , s2 , false , false ) )
253 return i ;
254 }
519cb848
SC
255 }
256 else
257 {
2f1ae414
SC
258 Str255 s1 , s2 ;
259 strcpy( (char*) s2 , s.c_str() ) ;
260 c2pstr( (char*) s2 ) ;
261 for ( int i = 0 ; i < m_noItems ; ++ i )
262 {
263 strcpy( (char*) s1 , m_stringArray[i].c_str() ) ;
264 c2pstr( (char*) s1 ) ;
265 if ( EqualString( s1 , s2 , false , false ) )
266 return i ;
267 }
519cb848
SC
268 }
269 return -1;
e9576ca5
SC
270}
271
272void wxListBox::Clear()
273{
e7549107 274 Free();
e9576ca5 275 m_noItems = 0;
519cb848
SC
276 m_stringArray.Empty() ;
277 m_dataArray.Empty() ;
278 MacClear() ;
e9576ca5
SC
279}
280
281void wxListBox::SetSelection(int N, bool select)
282{
519cb848
SC
283 wxCHECK_RET( N >= 0 && N < m_noItems,
284 "invalid index in wxListBox::SetSelection" );
285 MacSetSelection( N , select ) ;
e9576ca5
SC
286}
287
e7549107 288bool wxListBox::IsSelected(int N) const
e9576ca5 289{
519cb848
SC
290 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
291 "invalid index in wxListBox::Selected" );
292
293 return MacIsSelected( N ) ;
e9576ca5
SC
294}
295
e7549107 296void *wxListBox::DoGetItemClientData(int N) const
e9576ca5 297{
519cb848
SC
298 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
299 "invalid index in wxListBox::GetClientData" );
300
e7549107 301 return (void *)m_dataArray[N];
e9576ca5
SC
302}
303
51abe921
SC
304wxClientData *wxListBox::DoGetItemClientObject(int N) const
305{
306 return (wxClientData *) DoGetItemClientData( N ) ;
307}
308
e7549107 309void wxListBox::DoSetItemClientData(int N, void *Client_data)
e9576ca5 310{
519cb848
SC
311 wxCHECK_RET( N >= 0 && N < m_noItems,
312 "invalid index in wxListBox::SetClientData" );
313
e7549107
SC
314#if wxUSE_OWNER_DRAWN
315 if ( m_windowStyle & wxLB_OWNERDRAW )
316 {
317 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
318 // in OnMeasure/OnDraw.
319 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
320 }
321#endif // wxUSE_OWNER_DRAWN
8208e181
SC
322 wxASSERT_MSG( m_dataArray.GetCount() >= N , "invalid client_data array" ) ;
323
324 if ( m_dataArray.GetCount() > N )
325 {
326 m_dataArray[N] = (char*) Client_data ;
2f1ae414 327 }
8208e181
SC
328 else
329 {
330 m_dataArray.Add( (char*) Client_data ) ;
331 }
e7549107
SC
332}
333
334void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
335{
336 DoSetItemClientData(n, clientData);
e9576ca5
SC
337}
338
339// Return number of selections and an array of selected integers
340int wxListBox::GetSelections(wxArrayInt& aSelections) const
341{
519cb848 342 return MacGetSelections( aSelections ) ;
e9576ca5
SC
343
344/* TODO
519cb848 345 if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED))
e9576ca5
SC
346 {
347 int no_sel = ??
348 for ( int n = 0; n < no_sel; n++ )
349 aSelections.Add(??);
350
351 return no_sel;
352 }
353 else // single-selection listbox
354 {
355 aSelections.Add(??);
356
357 return 1;
358 }
359*/
e9576ca5
SC
360}
361
362// Get single selection, for single choice list items
363int wxListBox::GetSelection() const
364{
519cb848 365 return MacGetSelection() ;
e9576ca5
SC
366}
367
368// Find string for position
369wxString wxListBox::GetString(int N) const
370{
519cb848
SC
371 if( wxApp::s_macDefaultEncodingIsPC )
372 {
373 return wxMacMakePCStringFromMac( m_stringArray[N] ) ;
374 }
375 else
376 return m_stringArray[N] ;
e9576ca5
SC
377}
378
e7549107 379void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
e9576ca5 380{
e7549107
SC
381 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
382 wxT("invalid index in wxListBox::InsertItems") );
383
384 int nItems = items.GetCount();
385
519cb848
SC
386 for ( int i = 0 ; i < nItems ; i++ )
387 {
388 m_stringArray.Insert( items[i] , pos + i ) ;
389 m_dataArray.Insert( NULL , pos + i ) ;
390 MacInsert( pos + i , items[i] ) ;
391 }
e9576ca5 392
519cb848 393 m_noItems += nItems;
e9576ca5
SC
394}
395
396void wxListBox::SetString(int N, const wxString& s)
397{
2f1ae414
SC
398 wxString str ;
399 if( wxApp::s_macDefaultEncodingIsPC )
400 {
401 str = wxMacMakeMacStringFromPC( s ) ;
402 }
403 else
404 str = s ;
405 m_stringArray[N] = str ;
519cb848 406 MacSet( N , s ) ;
e9576ca5
SC
407}
408
37e2cb08 409wxSize wxListBox::DoGetBestSize() const
e9576ca5 410{
e7549107 411 return wxSize(100, 100);
e9576ca5
SC
412}
413
51abe921
SC
414int wxListBox::GetCount() const
415{
416 return m_noItems;
417}
418
419void wxListBox::SetupColours()
420{
421 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
422 SetForegroundColour(GetParent()->GetForegroundColour());
423}
424
425#if wxUSE_OWNER_DRAWN
426
427class wxListBoxItem : public wxOwnerDrawn
428{
429public:
430 wxListBoxItem(const wxString& str = "");
431};
432
433wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
434{
435 // no bitmaps/checkmarks
436 SetMarginWidth(0);
437}
438
439wxOwnerDrawn *wxListBox::CreateItem(size_t n)
440{
441 return new wxListBoxItem();
442}
443
444#endif //USE_OWNER_DRAWN
e9576ca5 445
519cb848
SC
446// ============================================================================
447// list box control implementation
448// ============================================================================
449
450void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon)
451{
452 wxListBox* list;
453 // typecast our refCon
454 list = (wxListBox*)refCon;
455
456 MoveTo(cellRect->left + 4 , cellRect->top + 10 );
457 const wxString text = list->m_stringArray[lCell.v] ;
458 ::TextFont( kFontIDMonaco ) ;
459 ::TextSize( 9 );
460 ::TextFace( 0 ) ;
461 DrawText(text, 0 , text.Length());
462
463}
464
465void wxListBox::MacDelete( int N )
466{
467 ListHandle list ;
468 long result ;
469 Cell cell = { 0 , 0 } ;
470 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxListHandleTag , sizeof( ListHandle ) , (char*) &list , &result ) ;
471 LDelRow( 1 , N , list ) ;
472}
473
474void wxListBox::MacInsert( int n , const char * text)
475{
476 Cell cell ;
477
478 cell.h = 0 ;
479 cell.v = n ;
480
481 LAddRow( 1 , cell.v , m_macList ) ;
482}
483
484void wxListBox::MacAppend( const char * text)
485{
486 Cell cell = { 0 , 0 } ;
487 cell.v = (**m_macList).dataBounds.bottom ;
488 LAddRow( 1 , cell.v , m_macList ) ;
489}
490
491void wxListBox::MacClear()
492{
493 LDelRow( (**m_macList).dataBounds.bottom , 0 , m_macList ) ;
494}
495
496void wxListBox::MacSetSelection( int n , bool select )
497{
498 Cell cell = { 0 , 0 } ;
499 if ( LGetSelect( TRUE , &cell , m_macList ) )
500 {
501 LSetSelect( false , cell , m_macList ) ;
502 }
503
504 cell.v = n ;
505 LSetSelect( select , cell , m_macList ) ;
506 LAutoScroll( m_macList ) ;
507}
508
509bool wxListBox::MacIsSelected( int n ) const
510{
511 Cell cell = { 0 , 0 } ;
512 cell.v = n ;
513 return LGetSelect( false , &cell , m_macList ) ;
514}
515
516void wxListBox::MacDestroy()
517{
518// DisposeExtLDEFInfo( m_macList ) ;
519}
520
521int wxListBox::MacGetSelection() const
522{
523 Cell cell = { 0 , 0 } ;
524 if ( LGetSelect( true , &cell , m_macList ) )
525 return cell.v ;
526 else
527 return -1 ;
528}
529
530int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
531{
532 int no_sel = 0 ;
533
534 aSelections.Empty();
535
536 Cell cell = { 0 , 0 } ;
537 cell.v = 0 ;
538
539 while ( LGetSelect( true , &cell , m_macList ) )
540 {
541 aSelections.Add( cell.v ) ;
542 no_sel++ ;
543 cell.v++ ;
544 }
545 return no_sel ;
546}
547
548void wxListBox::MacSet( int n , const char * text )
549{
550 // our implementation does not store anything in the list
551 // so we just have to redraw
552 Cell cell = { 0 , 0 } ;
553 cell.v = n ;
554 LDraw( cell , m_macList ) ;
555}
556
557void wxListBox::MacScrollTo( int n )
558{
559 // TODO implement scrolling
560}
561
562void wxListBox::OnSize( const wxSizeEvent &event)
563{
564 Point pt = (**m_macList).cellSize ;
2f1ae414 565 pt.h = m_width - 15 ;
519cb848
SC
566 LCellSize( pt , m_macList ) ;
567}
568
569void wxListBox::MacHandleControlClick( ControlHandle control , SInt16 controlpart )
570{
571 Boolean wasDoubleClick = false ;
572 long result ;
573
574 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxDoubleClickTag , sizeof( wasDoubleClick ) , (char*) &wasDoubleClick , &result ) ;
575 if ( !wasDoubleClick )
576 {
577 MacDoClick() ;
578 }
579 else
580 {
581 MacDoDoubleClick() ;
582 }
583}
584
585void wxListBox::MacSetRedraw( bool doDraw )
586{
587 LSetDrawingMode( doDraw , m_macList ) ;
588
589}
590
591void wxListBox::MacDoClick()
592{
593 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
e7549107
SC
594 event.SetEventObject( this );
595
519cb848 596 wxArrayInt aSelections;
e7549107 597 int n, count = GetSelections(aSelections);
519cb848
SC
598 if ( count > 0 )
599 {
7c74e7fe
SC
600 n = aSelections[0];
601 if ( HasClientObjectData() )
e7549107
SC
602 event.SetClientObject( GetClientObject(n) );
603 else if ( HasClientUntypedData() )
604 event.SetClientData( GetClientData(n) );
605 event.SetString( GetString(n) );
519cb848
SC
606 }
607 else
608 {
e7549107 609 n = -1;
519cb848
SC
610 }
611
e7549107
SC
612 event.m_commandInt = n;
613
614 GetEventHandler()->ProcessEvent(event);
519cb848
SC
615}
616
617void wxListBox::MacDoDoubleClick()
618{
619 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
620 event.SetEventObject( this );
621 GetEventHandler()->ProcessEvent(event) ;
622}