]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listbox.cpp
updated mac sources (CW 5.3 working , CW6 still having code gen problems)
[wxWidgets.git] / src / mac / carbon / listbox.cpp
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
21 #include "wx/utils.h"
22 #include "extldef.h"
23
24 #if !USE_SHARED_LIBRARY
25 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
26
27 BEGIN_EVENT_TABLE(wxListBox, wxControl)
28 EVT_SIZE( wxListBox::OnSize )
29 END_EVENT_TABLE()
30 #endif
31
32 #include <wx/mac/uma.h>
33
34 extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
35 const short kwxMacListWithVerticalScrollbar = 128 ;
36
37 // ============================================================================
38 // list box control implementation
39 // ============================================================================
40
41 // Listbox item
42 wxListBox::wxListBox()
43 {
44 m_noItems = 0;
45 m_selected = 0;
46 m_macList = NULL ;
47 }
48
49 bool 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 {
57 m_noItems = 0 ; // this will be increased by our append command
58 m_selected = 0;
59
60 Rect bounds ;
61 Str255 title ;
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
71 HLock( (Handle) m_macList ) ;
72 NewExtLDEFInfo( m_macList , MacDrawStringCell , (long) this ) ;
73 (**m_macList).selFlags = 0 ;
74 if ( style & wxLB_MULTIPLE )
75 {
76 (**m_macList).selFlags += lNoExtend ;
77 }
78 else if ( style & wxLB_EXTENDED )
79 {
80 (**m_macList).selFlags += lExtendDrag ;
81 }
82 else
83 {
84 (**m_macList).selFlags = lOnlyOne ;
85 }
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;
109 }
110
111 wxListBox::~wxListBox()
112 {
113 Free() ;
114 if ( m_macList )
115 {
116 DisposeExtLDEFInfo( m_macList ) ;
117 m_macList = NULL ;
118 }
119 }
120
121 void wxListBox::Free()
122 {
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 }
142 }
143
144 void wxListBox::DoSetFirstItem(int N)
145 {
146 MacScrollTo( N ) ;
147 }
148
149 void wxListBox::Delete(int N)
150 {
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
163 m_stringArray.Remove( N ) ;
164 m_dataArray.Remove( N ) ;
165 m_noItems --;
166
167 MacDelete( N ) ;
168 }
169
170 int wxListBox::DoAppend(const wxString& item)
171 {
172 int index = m_noItems ;
173 if( wxApp::s_macDefaultEncodingIsPC )
174 {
175 m_stringArray.Add( wxMacMakeMacStringFromPC( item ) ) ;
176 m_dataArray.Add( NULL );
177 }
178 else {
179 m_stringArray.Add( item ) ;
180 m_dataArray.Add( NULL );
181 }
182 m_noItems ++;
183 DoSetItemClientData( index , NULL ) ;
184 MacAppend( item ) ;
185
186 return index ;
187 }
188
189 void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
190 {
191 MacSetRedraw( false ) ;
192 Clear() ;
193 int n = choices.GetCount();
194
195 for( int i = 0 ; i < n ; ++i )
196 {
197 if ( clientData )
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
203 Append( choices[i] , clientData[i] ) ;
204 #endif
205 }
206 else
207 Append( choices[i] ) ;
208 }
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
230 bool wxListBox::HasMultipleSelection() const
231 {
232 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
233 }
234
235 int wxListBox::FindString(const wxString& st) const
236 {
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() ;
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 }
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
269 }
270 else
271 {
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 }
282 }
283 return -1;
284 }
285
286 void wxListBox::Clear()
287 {
288 Free();
289 m_noItems = 0;
290 m_stringArray.Empty() ;
291 m_dataArray.Empty() ;
292 MacClear() ;
293 }
294
295 void wxListBox::SetSelection(int N, bool select)
296 {
297 wxCHECK_RET( N >= 0 && N < m_noItems,
298 "invalid index in wxListBox::SetSelection" );
299 MacSetSelection( N , select ) ;
300 }
301
302 bool wxListBox::IsSelected(int N) const
303 {
304 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
305 "invalid index in wxListBox::Selected" );
306
307 return MacIsSelected( N ) ;
308 }
309
310 void *wxListBox::DoGetItemClientData(int N) const
311 {
312 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
313 "invalid index in wxListBox::GetClientData" );
314
315 return (void *)m_dataArray[N];
316 }
317
318 wxClientData *wxListBox::DoGetItemClientObject(int N) const
319 {
320 return (wxClientData *) DoGetItemClientData( N ) ;
321 }
322
323 void wxListBox::DoSetItemClientData(int N, void *Client_data)
324 {
325 wxCHECK_RET( N >= 0 && N < m_noItems,
326 "invalid index in wxListBox::SetClientData" );
327
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
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 ;
341 }
342 else
343 {
344 m_dataArray.Add( (char*) Client_data ) ;
345 }
346 }
347
348 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
349 {
350 DoSetItemClientData(n, clientData);
351 }
352
353 // Return number of selections and an array of selected integers
354 int wxListBox::GetSelections(wxArrayInt& aSelections) const
355 {
356 return MacGetSelections( aSelections ) ;
357
358 /* TODO
359 if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED))
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 */
374 }
375
376 // Get single selection, for single choice list items
377 int wxListBox::GetSelection() const
378 {
379 return MacGetSelection() ;
380 }
381
382 // Find string for position
383 wxString wxListBox::GetString(int N) const
384 {
385 if( wxApp::s_macDefaultEncodingIsPC )
386 {
387 return wxMacMakePCStringFromMac( m_stringArray[N] ) ;
388 }
389 else
390 return m_stringArray[N] ;
391 }
392
393 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
394 {
395 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
396 wxT("invalid index in wxListBox::InsertItems") );
397
398 int nItems = items.GetCount();
399
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 }
406
407 m_noItems += nItems;
408 }
409
410 void wxListBox::SetString(int N, const wxString& s)
411 {
412 wxString str ;
413 if( wxApp::s_macDefaultEncodingIsPC )
414 {
415 str = wxMacMakeMacStringFromPC( s ) ;
416 }
417 else
418 str = s ;
419 m_stringArray[N] = str ;
420 MacSet( N , s ) ;
421 }
422
423 wxSize wxListBox::DoGetBestSize() const
424 {
425 return wxSize(100, 100);
426 }
427
428 int wxListBox::GetCount() const
429 {
430 return m_noItems;
431 }
432
433 void wxListBox::SetupColours()
434 {
435 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
436 SetForegroundColour(GetParent()->GetForegroundColour());
437 }
438
439 #if wxUSE_OWNER_DRAWN
440
441 class wxListBoxItem : public wxOwnerDrawn
442 {
443 public:
444 wxListBoxItem(const wxString& str = "");
445 };
446
447 wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
448 {
449 // no bitmaps/checkmarks
450 SetMarginWidth(0);
451 }
452
453 wxOwnerDrawn *wxListBox::CreateItem(size_t n)
454 {
455 return new wxListBoxItem();
456 }
457
458 #endif //USE_OWNER_DRAWN
459
460 // ============================================================================
461 // list box control implementation
462 // ============================================================================
463
464 void 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
479 void 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
488 void 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
498 void 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
505 void wxListBox::MacClear()
506 {
507 LDelRow( (**m_macList).dataBounds.bottom , 0 , m_macList ) ;
508 }
509
510 void 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
523 bool wxListBox::MacIsSelected( int n ) const
524 {
525 Cell cell = { 0 , 0 } ;
526 cell.v = n ;
527 return LGetSelect( false , &cell , m_macList ) ;
528 }
529
530 void wxListBox::MacDestroy()
531 {
532 // DisposeExtLDEFInfo( m_macList ) ;
533 }
534
535 int 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
544 int 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
562 void 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
571 void wxListBox::MacScrollTo( int n )
572 {
573 // TODO implement scrolling
574 }
575
576 void wxListBox::OnSize( const wxSizeEvent &event)
577 {
578 Point pt = (**m_macList).cellSize ;
579 pt.h = m_width - 15 ;
580 LCellSize( pt , m_macList ) ;
581 }
582
583 void 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
599 void wxListBox::MacSetRedraw( bool doDraw )
600 {
601 LSetDrawingMode( doDraw , m_macList ) ;
602
603 }
604
605 void wxListBox::MacDoClick()
606 {
607 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
608 event.SetEventObject( this );
609
610 wxArrayInt aSelections;
611 int n, count = GetSelections(aSelections);
612 if ( count > 0 )
613 {
614 n = aSelections[0];
615 if ( HasClientObjectData() )
616 event.SetClientObject( GetClientObject(n) );
617 else if ( HasClientUntypedData() )
618 event.SetClientData( GetClientData(n) );
619 event.SetString( GetString(n) );
620 }
621 else
622 {
623 n = -1;
624 }
625
626 event.m_commandInt = n;
627
628 GetEventHandler()->ProcessEvent(event);
629 }
630
631 void wxListBox::MacDoDoubleClick()
632 {
633 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
634 event.SetEventObject( this );
635 GetEventHandler()->ProcessEvent(event) ;
636 }