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