]> git.saurik.com Git - wxWidgets.git/blob - src/mac/listbox.cpp
Added child window scrolling
[wxWidgets.git] / src / mac / 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 }
177 else
178 m_stringArray.Add( item ) ;
179 m_noItems ++;
180 MacAppend( item ) ;
181
182 return index ;
183 }
184
185 void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
186 {
187 MacSetRedraw( false ) ;
188 Clear() ;
189 int n = choices.GetCount();
190
191 for( int i = 0 ; i < n ; ++i )
192 {
193 if ( clientData )
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
199 Append( choices[i] , clientData[i] ) ;
200 #endif
201 }
202 else
203 Append( choices[i] ) ;
204 }
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
226 bool wxListBox::HasMultipleSelection() const
227 {
228 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
229 }
230
231 int wxListBox::FindString(const wxString& st) const
232 {
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() ;
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 }
255 }
256 else
257 {
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 }
268 }
269 return -1;
270 }
271
272 void wxListBox::Clear()
273 {
274 Free();
275 m_noItems = 0;
276 m_stringArray.Empty() ;
277 m_dataArray.Empty() ;
278 MacClear() ;
279 }
280
281 void wxListBox::SetSelection(int N, bool select)
282 {
283 wxCHECK_RET( N >= 0 && N < m_noItems,
284 "invalid index in wxListBox::SetSelection" );
285 MacSetSelection( N , select ) ;
286 }
287
288 bool wxListBox::IsSelected(int N) const
289 {
290 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
291 "invalid index in wxListBox::Selected" );
292
293 return MacIsSelected( N ) ;
294 }
295
296 void *wxListBox::DoGetItemClientData(int N) const
297 {
298 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
299 "invalid index in wxListBox::GetClientData" );
300
301 return (void *)m_dataArray[N];
302 }
303
304 wxClientData *wxListBox::DoGetItemClientObject(int N) const
305 {
306 return (wxClientData *) DoGetItemClientData( N ) ;
307 }
308
309 void wxListBox::DoSetItemClientData(int N, void *Client_data)
310 {
311 wxCHECK_RET( N >= 0 && N < m_noItems,
312 "invalid index in wxListBox::SetClientData" );
313
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
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 ;
327 }
328 else
329 {
330 m_dataArray.Add( (char*) Client_data ) ;
331 }
332 }
333
334 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
335 {
336 DoSetItemClientData(n, clientData);
337 }
338
339 // Return number of selections and an array of selected integers
340 int wxListBox::GetSelections(wxArrayInt& aSelections) const
341 {
342 return MacGetSelections( aSelections ) ;
343
344 /* TODO
345 if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED))
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 */
360 }
361
362 // Get single selection, for single choice list items
363 int wxListBox::GetSelection() const
364 {
365 return MacGetSelection() ;
366 }
367
368 // Find string for position
369 wxString wxListBox::GetString(int N) const
370 {
371 if( wxApp::s_macDefaultEncodingIsPC )
372 {
373 return wxMacMakePCStringFromMac( m_stringArray[N] ) ;
374 }
375 else
376 return m_stringArray[N] ;
377 }
378
379 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
380 {
381 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
382 wxT("invalid index in wxListBox::InsertItems") );
383
384 int nItems = items.GetCount();
385
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 }
392
393 m_noItems += nItems;
394 }
395
396 void wxListBox::SetString(int N, const wxString& s)
397 {
398 wxString str ;
399 if( wxApp::s_macDefaultEncodingIsPC )
400 {
401 str = wxMacMakeMacStringFromPC( s ) ;
402 }
403 else
404 str = s ;
405 m_stringArray[N] = str ;
406 MacSet( N , s ) ;
407 }
408
409 wxSize wxListBox::DoGetBestSize() const
410 {
411 return wxSize(100, 100);
412 }
413
414 int wxListBox::GetCount() const
415 {
416 return m_noItems;
417 }
418
419 void wxListBox::SetupColours()
420 {
421 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
422 SetForegroundColour(GetParent()->GetForegroundColour());
423 }
424
425 #if wxUSE_OWNER_DRAWN
426
427 class wxListBoxItem : public wxOwnerDrawn
428 {
429 public:
430 wxListBoxItem(const wxString& str = "");
431 };
432
433 wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
434 {
435 // no bitmaps/checkmarks
436 SetMarginWidth(0);
437 }
438
439 wxOwnerDrawn *wxListBox::CreateItem(size_t n)
440 {
441 return new wxListBoxItem();
442 }
443
444 #endif //USE_OWNER_DRAWN
445
446 // ============================================================================
447 // list box control implementation
448 // ============================================================================
449
450 void 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
465 void 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
474 void 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
484 void 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
491 void wxListBox::MacClear()
492 {
493 LDelRow( (**m_macList).dataBounds.bottom , 0 , m_macList ) ;
494 }
495
496 void 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
509 bool wxListBox::MacIsSelected( int n ) const
510 {
511 Cell cell = { 0 , 0 } ;
512 cell.v = n ;
513 return LGetSelect( false , &cell , m_macList ) ;
514 }
515
516 void wxListBox::MacDestroy()
517 {
518 // DisposeExtLDEFInfo( m_macList ) ;
519 }
520
521 int 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
530 int 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
548 void 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
557 void wxListBox::MacScrollTo( int n )
558 {
559 // TODO implement scrolling
560 }
561
562 void wxListBox::OnSize( const wxSizeEvent &event)
563 {
564 Point pt = (**m_macList).cellSize ;
565 pt.h = m_width - 15 ;
566 LCellSize( pt , m_macList ) ;
567 }
568
569 void 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
585 void wxListBox::MacSetRedraw( bool doDraw )
586 {
587 LSetDrawingMode( doDraw , m_macList ) ;
588
589 }
590
591 void wxListBox::MacDoClick()
592 {
593 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
594 event.SetEventObject( this );
595
596 wxArrayInt aSelections;
597 int n, count = GetSelections(aSelections);
598 if ( count > 0 )
599 {
600 n = aSelections[0];
601 if ( HasClientObjectData() )
602 event.SetClientObject( GetClientObject(n) );
603 else if ( HasClientUntypedData() )
604 event.SetClientData( GetClientData(n) );
605 event.SetString( GetString(n) );
606 }
607 else
608 {
609 n = -1;
610 }
611
612 event.m_commandInt = n;
613
614 GetEventHandler()->ProcessEvent(event);
615 }
616
617 void wxListBox::MacDoDoubleClick()
618 {
619 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
620 event.SetEventObject( this );
621 GetEventHandler()->ProcessEvent(event) ;
622 }