]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/listbox.cpp
3b9c54ce7779c6968ae3dc2fd1d93f7225ac5fca
[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 }
47
48 bool wxListBox::Create(wxWindow *parent, wxWindowID id,
49 const wxPoint& pos,
50 const wxSize& size,
51 int n, const wxString choices[],
52 long style,
53 const wxValidator& validator,
54 const wxString& name)
55 {
56 m_noItems = 0 ; // this will be increased by our append command
57 m_selected = 0;
58
59 Rect bounds ;
60 Str255 title ;
61 m_macHorizontalBorder = 5 ; // additional pixels around the real control
62 m_macVerticalBorder = 5 ;
63
64 MacPreControlCreate( parent , id , "" , pos , size ,style, validator , name , &bounds , title ) ;
65
66 m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , title , true , kwxMacListWithVerticalScrollbar , 0 , 0,
67 kControlListBoxProc , (long) this ) ;
68
69 long result ;
70 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxListHandleTag , sizeof( ListHandle ) , (char*) &m_macList , &result ) ;
71
72 NewExtLDEFInfo( m_macList , MacDrawStringCell , (long) this ) ;
73 (**m_macList).selFlags = lOnlyOne ;
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 Point pt = (**m_macList).cellSize ;
83 pt.v = 14 ;
84 LCellSize( pt , m_macList ) ;
85
86 LAddColumn( 1 , 0 , m_macList ) ;
87
88 MacPostControlCreate() ;
89
90 ControlFontStyleRec controlstyle ;
91 controlstyle.flags = kControlUseFontMask + kControlUseSizeMask ;
92 //controlstyle.font = kControlFontSmallSystemFont ;
93 controlstyle.font = kFontIDMonaco ;
94 controlstyle.size = 9 ;
95 ::UMASetControlFontStyle( m_macControl , &controlstyle ) ;
96
97 for ( int i = 0 ; i < n ; i++ )
98 {
99 Append( choices[i] ) ;
100 }
101
102 LSetDrawingMode( true , m_macList ) ;
103
104 return TRUE;
105 }
106
107 wxListBox::~wxListBox()
108 {
109 Free() ;
110 DisposeExtLDEFInfo( m_macList ) ;
111 }
112
113 void wxListBox::Free()
114 {
115 #if wxUSE_OWNER_DRAWN
116 if ( m_windowStyle & wxLB_OWNERDRAW )
117 {
118 size_t uiCount = m_aItems.Count();
119 while ( uiCount-- != 0 ) {
120 delete m_aItems[uiCount];
121 }
122
123 m_aItems.Clear();
124 }
125 else
126 #endif // wxUSE_OWNER_DRAWN
127 if ( HasClientObjectData() )
128 {
129 for ( size_t n = 0; n < (size_t)m_noItems; n++ )
130 {
131 delete GetClientObject(n);
132 }
133 }
134 }
135
136 void wxListBox::DoSetFirstItem(int N)
137 {
138 MacScrollTo( N ) ;
139 }
140
141 void wxListBox::Delete(int N)
142 {
143 wxCHECK_RET( N >= 0 && N < m_noItems,
144 wxT("invalid index in wxListBox::Delete") );
145
146 #if wxUSE_OWNER_DRAWN
147 delete m_aItems[N];
148 m_aItems.Remove(N);
149 #else // !wxUSE_OWNER_DRAWN
150 if ( HasClientObjectData() )
151 {
152 delete GetClientObject(N);
153 }
154 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
155 m_stringArray.Remove( N ) ;
156 m_noItems --;
157
158 MacDelete( N ) ;
159 SetHorizontalExtent("");
160 }
161
162 int wxListBox::DoAppend(const wxString& item)
163 {
164 int index = m_noItems ;
165 if( wxApp::s_macDefaultEncodingIsPC )
166 {
167 m_stringArray.Add( wxMacMakeMacStringFromPC( item ) ) ;
168 }
169 else
170 m_stringArray.Add( item ) ;
171 m_noItems ++;
172 MacAppend( item ) ;
173
174 SetHorizontalExtent(item);
175
176 return index ;
177 }
178
179 void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
180 {
181 MacSetRedraw( false ) ;
182 Clear() ;
183 int n = choices.GetCount();
184
185 for( int i = 0 ; i < n ; ++i )
186 {
187 if ( clientData )
188 {
189 #if wxUSE_OWNER_DRAWN
190 wxASSERT_MSG(clientData[i] == NULL,
191 wxT("Can't use client data with owner-drawn listboxes"));
192 #else // !wxUSE_OWNER_DRAWN
193 Append( choices[i] , clientData[0] ) ;
194 #endif
195 }
196 else
197 Append( choices[i] ) ;
198 }
199
200 #if wxUSE_OWNER_DRAWN
201 if ( m_windowStyle & wxLB_OWNERDRAW ) {
202 // first delete old items
203 size_t ui = m_aItems.Count();
204 while ( ui-- != 0 ) {
205 delete m_aItems[ui];
206 }
207 m_aItems.Empty();
208
209 // then create new ones
210 for ( ui = 0; ui < (size_t)m_noItems; ui++ ) {
211 wxOwnerDrawn *pNewItem = CreateItem(ui);
212 pNewItem->SetName(choices[ui]);
213 m_aItems.Add(pNewItem);
214 }
215 }
216 #endif // wxUSE_OWNER_DRAWN
217 MacSetRedraw( true ) ;
218 }
219
220 bool wxListBox::HasMultipleSelection() const
221 {
222 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
223 }
224
225 int wxListBox::FindString(const wxString& st) const
226 {
227 wxString s ;
228 if( wxApp::s_macDefaultEncodingIsPC )
229 {
230 s = wxMacMakeMacStringFromPC( st ) ;
231 }
232 else
233 s = st ;
234
235 if ( s.Right(1) == "*" )
236 {
237 wxString search = s.Left( s.Length() - 1 ) ;
238 int len = search.Length() ;
239 for ( int i = 0 ; i < m_noItems ; ++ i )
240 {
241 if ( equalstring( m_stringArray[i].Left( len ) , search , false , false ) )
242 return i ;
243 }
244 }
245 else
246 {
247 for ( int i = 0 ; i < m_noItems ; ++ i )
248 {
249 if ( equalstring( m_stringArray[i] , s , false , false ) )
250 return i ;
251 }
252 }
253 return -1;
254 }
255
256 void wxListBox::Clear()
257 {
258 Free();
259 m_noItems = 0;
260 m_stringArray.Empty() ;
261 m_dataArray.Empty() ;
262 MacClear() ;
263 SetHorizontalExtent();
264 }
265
266 void wxListBox::SetSelection(int N, bool select)
267 {
268 wxCHECK_RET( N >= 0 && N < m_noItems,
269 "invalid index in wxListBox::SetSelection" );
270 MacSetSelection( N , select ) ;
271 }
272
273 bool wxListBox::IsSelected(int N) const
274 {
275 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
276 "invalid index in wxListBox::Selected" );
277
278 return MacIsSelected( N ) ;
279 }
280
281 void *wxListBox::DoGetItemClientData(int N) const
282 {
283 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
284 "invalid index in wxListBox::GetClientData" );
285
286 return (void *)m_dataArray[N];
287 }
288
289 void wxListBox::DoSetItemClientData(int N, void *Client_data)
290 {
291 wxCHECK_RET( N >= 0 && N < m_noItems,
292 "invalid index in wxListBox::SetClientData" );
293
294 #if wxUSE_OWNER_DRAWN
295 if ( m_windowStyle & wxLB_OWNERDRAW )
296 {
297 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
298 // in OnMeasure/OnDraw.
299 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
300 }
301 #endif // wxUSE_OWNER_DRAWN
302 m_dataArray[N] = (char*) Client_data ;
303 }
304
305 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
306 {
307 DoSetItemClientData(n, clientData);
308 }
309
310 // Return number of selections and an array of selected integers
311 int wxListBox::GetSelections(wxArrayInt& aSelections) const
312 {
313 return MacGetSelections( aSelections ) ;
314
315 /* TODO
316 if ((m_windowStyle & wxLB_MULTIMacE) || (m_windowStyle & wxLB_EXTENDED))
317 {
318 int no_sel = ??
319 for ( int n = 0; n < no_sel; n++ )
320 aSelections.Add(??);
321
322 return no_sel;
323 }
324 else // single-selection listbox
325 {
326 aSelections.Add(??);
327
328 return 1;
329 }
330 */
331 }
332
333 // Get single selection, for single choice list items
334 int wxListBox::GetSelection() const
335 {
336 return MacGetSelection() ;
337 }
338
339 // Find string for position
340 wxString wxListBox::GetString(int N) const
341 {
342 if( wxApp::s_macDefaultEncodingIsPC )
343 {
344 return wxMacMakePCStringFromMac( m_stringArray[N] ) ;
345 }
346 else
347 return m_stringArray[N] ;
348 }
349
350 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
351 {
352 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
353 wxT("invalid index in wxListBox::InsertItems") );
354
355 int nItems = items.GetCount();
356
357 for ( int i = 0 ; i < nItems ; i++ )
358 {
359 m_stringArray.Insert( items[i] , pos + i ) ;
360 m_dataArray.Insert( NULL , pos + i ) ;
361 MacInsert( pos + i , items[i] ) ;
362 }
363
364 m_noItems += nItems;
365 }
366
367 void wxListBox::SetString(int N, const wxString& s)
368 {
369 m_stringArray[N] = s ;
370 MacSet( N , s ) ;
371 }
372
373 wxSize wxListBox::DoGetBestSize()
374 {
375 return wxSize(100, 100);
376 }
377
378
379 // ============================================================================
380 // list box control implementation
381 // ============================================================================
382
383 void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon)
384 {
385 wxListBox* list;
386 // typecast our refCon
387 list = (wxListBox*)refCon;
388
389 MoveTo(cellRect->left + 4 , cellRect->top + 10 );
390 const wxString text = list->m_stringArray[lCell.v] ;
391 ::TextFont( kFontIDMonaco ) ;
392 ::TextSize( 9 );
393 ::TextFace( 0 ) ;
394 DrawText(text, 0 , text.Length());
395
396 }
397
398 void wxListBox::MacDelete( int N )
399 {
400 ListHandle list ;
401 long result ;
402 Cell cell = { 0 , 0 } ;
403 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxListHandleTag , sizeof( ListHandle ) , (char*) &list , &result ) ;
404 LDelRow( 1 , N , list ) ;
405 }
406
407 void wxListBox::MacInsert( int n , const char * text)
408 {
409 Cell cell ;
410
411 cell.h = 0 ;
412 cell.v = n ;
413
414 LAddRow( 1 , cell.v , m_macList ) ;
415 }
416
417 void wxListBox::MacAppend( const char * text)
418 {
419 Cell cell = { 0 , 0 } ;
420 cell.v = (**m_macList).dataBounds.bottom ;
421 LAddRow( 1 , cell.v , m_macList ) ;
422 }
423
424 void wxListBox::MacClear()
425 {
426 LDelRow( (**m_macList).dataBounds.bottom , 0 , m_macList ) ;
427 }
428
429 void wxListBox::MacSetSelection( int n , bool select )
430 {
431 Cell cell = { 0 , 0 } ;
432 if ( LGetSelect( TRUE , &cell , m_macList ) )
433 {
434 LSetSelect( false , cell , m_macList ) ;
435 }
436
437 cell.v = n ;
438 LSetSelect( select , cell , m_macList ) ;
439 LAutoScroll( m_macList ) ;
440 }
441
442 bool wxListBox::MacIsSelected( int n ) const
443 {
444 Cell cell = { 0 , 0 } ;
445 cell.v = n ;
446 return LGetSelect( false , &cell , m_macList ) ;
447 }
448
449 void wxListBox::MacDestroy()
450 {
451 // DisposeExtLDEFInfo( m_macList ) ;
452 }
453
454 int wxListBox::MacGetSelection() const
455 {
456 Cell cell = { 0 , 0 } ;
457 if ( LGetSelect( true , &cell , m_macList ) )
458 return cell.v ;
459 else
460 return -1 ;
461 }
462
463 int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
464 {
465 int no_sel = 0 ;
466
467 aSelections.Empty();
468
469 Cell cell = { 0 , 0 } ;
470 cell.v = 0 ;
471
472 while ( LGetSelect( true , &cell , m_macList ) )
473 {
474 aSelections.Add( cell.v ) ;
475 no_sel++ ;
476 cell.v++ ;
477 }
478 return no_sel ;
479 }
480
481 void wxListBox::MacSet( int n , const char * text )
482 {
483 // our implementation does not store anything in the list
484 // so we just have to redraw
485 Cell cell = { 0 , 0 } ;
486 cell.v = n ;
487 LDraw( cell , m_macList ) ;
488 }
489
490 void wxListBox::MacScrollTo( int n )
491 {
492 // TODO implement scrolling
493 }
494
495 void wxListBox::OnSize( const wxSizeEvent &event)
496 {
497 Point pt = (**m_macList).cellSize ;
498 pt.h = m_width - 15 /* scrollbar */ - m_macHorizontalBorder * 2 ;
499 LCellSize( pt , m_macList ) ;
500 }
501
502 void wxListBox::MacHandleControlClick( ControlHandle control , SInt16 controlpart )
503 {
504 Boolean wasDoubleClick = false ;
505 long result ;
506
507 UMAGetControlData( m_macControl , kControlNoPart , kControlListBoxDoubleClickTag , sizeof( wasDoubleClick ) , (char*) &wasDoubleClick , &result ) ;
508 if ( !wasDoubleClick )
509 {
510 MacDoClick() ;
511 }
512 else
513 {
514 MacDoDoubleClick() ;
515 }
516 }
517
518 void wxListBox::MacSetRedraw( bool doDraw )
519 {
520 LSetDrawingMode( doDraw , m_macList ) ;
521
522 }
523
524 void wxListBox::MacDoClick()
525 {
526 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
527 event.SetEventObject( this );
528
529 wxArrayInt aSelections;
530 int n, count = GetSelections(aSelections);
531 if ( count > 0 )
532 {
533 event.m_commandInt = aSelections[0] ;
534 if ( HasClientObjectData() )
535 event.SetClientObject( GetClientObject(n) );
536 else if ( HasClientUntypedData() )
537 event.SetClientData( GetClientData(n) );
538 event.SetString( GetString(n) );
539 }
540 else
541 {
542 n = -1;
543 }
544
545 event.m_commandInt = n;
546
547 GetEventHandler()->ProcessEvent(event);
548 }
549
550 void wxListBox::MacDoDoubleClick()
551 {
552 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
553 event.SetEventObject( this );
554 GetEventHandler()->ProcessEvent(event) ;
555 }