]> git.saurik.com Git - wxWidgets.git/blame - src/mac/classic/listbox.cpp
Include wx/pen.h according to precompiled headers of wx/wx.h (with other minor cleaning).
[wxWidgets.git] / src / mac / classic / listbox.cpp
CommitLineData
2646f485 1///////////////////////////////////////////////////////////////////////////////
11e62fe6 2// Name: src/mac/classic/listbox.cpp
2646f485
SC
3// Purpose: wxListBox
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
2646f485
SC
10///////////////////////////////////////////////////////////////////////////////
11
8228b893
WS
12#include "wx/wxprec.h"
13
14#if wxUSE_LISTBOX
15
e4db172a
WS
16#include "wx/listbox.h"
17
ad9835c9
WS
18#ifndef WX_PRECOMP
19 #include "wx/dynarray.h"
e4db172a 20 #include "wx/log.h"
670f9935 21 #include "wx/app.h"
de6185e2 22 #include "wx/utils.h"
f1e01716 23 #include "wx/button.h"
ad9835c9
WS
24#endif
25
2646f485
SC
26#include "wx/settings.h"
27#include "wx/toplevel.h"
2646f485 28
2646f485
SC
29IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
30
31BEGIN_EVENT_TABLE(wxListBox, wxControl)
32 EVT_SIZE( wxListBox::OnSize )
33 EVT_CHAR( wxListBox::OnChar )
34END_EVENT_TABLE()
2646f485
SC
35
36#include "wx/mac/uma.h"
37
38#if PRAGMA_STRUCT_ALIGN
39 #pragma options align=mac68k
40#elif PRAGMA_STRUCT_PACKPUSH
41 #pragma pack(push, 2)
42#elif PRAGMA_STRUCT_PACK
43 #pragma pack(2)
44#endif
45
46typedef struct {
47 unsigned short instruction;
48 void (*function)();
49} ldefRec, *ldefPtr, **ldefHandle;
50
51#if PRAGMA_STRUCT_ALIGN
52 #pragma options align=reset
53#elif PRAGMA_STRUCT_PACKPUSH
54 #pragma pack(pop)
55#elif PRAGMA_STRUCT_PACK
56 #pragma pack()
57#endif
58
59#if TARGET_CARBON
60const short kwxMacListItemHeight = 19 ;
61#else
62const short kwxMacListItemHeight = 14 ;
63#endif
64
65extern "C"
66{
67static pascal void wxMacListDefinition( short message, Boolean isSelected, Rect *drawRect,
68 Cell cell, short dataOffset, short dataLength,
69 ListHandle listHandle ) ;
70}
71
72static pascal void wxMacListDefinition( short message, Boolean isSelected, Rect *drawRect,
73 Cell cell, short dataOffset, short dataLength,
74 ListHandle listHandle )
75{
76 wxListBox* list;
77 list = (wxListBox*) GetControlReference( (ControlHandle) GetListRefCon(listHandle) );
78 if ( list == NULL )
79 return ;
11e62fe6 80
2646f485
SC
81 GrafPtr savePort;
82 GrafPtr grafPtr;
83 RgnHandle savedClipRegion;
84 SInt32 savedPenMode;
85 GetPort(&savePort);
86 SetPort((**listHandle).port);
87 grafPtr = (**listHandle).port ;
88 // typecast our refCon
11e62fe6 89
2646f485 90 // Calculate the cell rect.
11e62fe6 91
2646f485
SC
92 switch( message ) {
93 case lInitMsg:
94 break;
11e62fe6 95
2646f485
SC
96 case lCloseMsg:
97 break;
11e62fe6 98
2646f485
SC
99 case lDrawMsg:
100 {
101 const wxString linetext = list->m_stringArray[cell.v] ;
11e62fe6 102
2646f485
SC
103 // Save the current clip region, and set the clip region to the area we are about
104 // to draw.
11e62fe6 105
2646f485
SC
106 savedClipRegion = NewRgn();
107 GetClip( savedClipRegion );
11e62fe6 108
2646f485
SC
109 ClipRect( drawRect );
110 EraseRect( drawRect );
11e62fe6 111
2646f485
SC
112 const wxFont& font = list->GetFont();
113 if ( font.Ok() )
114 {
115 ::TextFont( font.GetMacFontNum() ) ;
116 ::TextSize( font.GetMacFontSize() ) ;
117 ::TextFace( font.GetMacFontStyle() ) ;
118 }
119 else
120 {
121 ::TextFont( kFontIDMonaco ) ;
122 ::TextSize( 9 );
123 ::TextFace( 0 ) ;
124 }
11e62fe6 125
2646f485 126#if TARGET_CARBON
11e62fe6
WS
127 {
128 Rect frame = { drawRect->top, drawRect->left + 4,
129 drawRect->top + kwxMacListItemHeight, drawRect->right + 10000 } ;
130 CFMutableStringRef mString = CFStringCreateMutableCopy( NULL , 0 , wxMacCFStringHolder(linetext , list->GetFont().GetEncoding()) ) ;
131 ::TruncateThemeText( mString , kThemeCurrentPortFont, kThemeStateActive, drawRect->right - drawRect->left , truncEnd , NULL ) ;
132 ::DrawThemeTextBox( mString,
133 kThemeCurrentPortFont,
134 kThemeStateActive,
135 false,
136 &frame,
137 teJustLeft,
138 nil );
139 CFRelease( mString ) ;
140 }
2646f485 141#else
11e62fe6
WS
142 {
143 wxCharBuffer text = linetext.mb_str( wxConvLocal) ;
2646f485
SC
144 MoveTo(drawRect->left + 4 , drawRect->top + 10 );
145 DrawText(text, 0 , strlen(text) );
146 }
11e62fe6 147#endif
2646f485
SC
148 // If the cell is hilited, do the hilite now. Paint the cell contents with the
149 // appropriate QuickDraw transform mode.
11e62fe6 150
2646f485
SC
151 if( isSelected ) {
152 savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
153 SetPortPenMode( (CGrafPtr)grafPtr, hilitetransfermode );
154 PaintRect( drawRect );
155 SetPortPenMode( (CGrafPtr)grafPtr, savedPenMode );
156 }
11e62fe6 157
2646f485 158 // Restore the saved clip region.
11e62fe6 159
2646f485
SC
160 SetClip( savedClipRegion );
161 DisposeRgn( savedClipRegion );
162 }
163 break;
164 case lHiliteMsg:
11e62fe6 165
2646f485
SC
166 // Hilite or unhilite the cell. Paint the cell contents with the
167 // appropriate QuickDraw transform mode.
11e62fe6 168
2646f485
SC
169 GetPort( &grafPtr );
170 savedPenMode = GetPortPenMode( (CGrafPtr)grafPtr );
171 SetPortPenMode( (CGrafPtr)grafPtr, hilitetransfermode );
172 PaintRect( drawRect );
173 SetPortPenMode( (CGrafPtr)grafPtr, savedPenMode );
174 break;
175 default :
176 break ;
177 }
178 SetPort(savePort);
179}
180
181extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
182// resources ldef ids
183const short kwxMacListWithVerticalScrollbar = 128 ;
184const short kwxMacListWithVerticalAndHorizontalScrollbar = 129 ;
185
186// ============================================================================
187// list box control implementation
188// ============================================================================
189
190// Listbox item
191wxListBox::wxListBox()
192{
193 m_noItems = 0;
194 m_selected = 0;
195 m_macList = NULL ;
196}
197
198static ListDefUPP macListDefUPP = NULL ;
199
200bool wxListBox::Create(wxWindow *parent, wxWindowID id,
201 const wxPoint& pos,
202 const wxSize& size,
203 const wxArrayString& choices,
204 long style,
205 const wxValidator& validator,
206 const wxString& name)
207{
208 wxCArrayString chs(choices);
209
210 return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
211 style, validator, name);
212}
213
214bool wxListBox::Create(wxWindow *parent, wxWindowID id,
215 const wxPoint& pos,
216 const wxSize& size,
217 int n, const wxString choices[],
218 long style,
219 const wxValidator& validator,
220 const wxString& name)
221{
222 if ( !wxListBoxBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
223 return false;
224
225 m_noItems = 0 ; // this will be increased by our append command
226 m_selected = 0;
227
228 Rect bounds ;
229 Str255 title ;
11e62fe6 230
2646f485 231 MacPreControlCreate( parent , id , wxEmptyString , pos , size ,style, validator , name , &bounds , title ) ;
11e62fe6 232
2646f485
SC
233 ListDefSpec listDef;
234 listDef.defType = kListDefUserProcType;
235 if ( macListDefUPP == NULL )
236 {
237 macListDefUPP = NewListDefUPP( wxMacListDefinition );
238 }
239 listDef.u.userProc = macListDefUPP ;
11e62fe6 240
2646f485
SC
241 Str255 fontName ;
242 SInt16 fontSize ;
243 Style fontStyle ;
244#if TARGET_CARBON
245 GetThemeFont(kThemeViewsFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
246#else
247 GetFontName( kFontIDMonaco , fontName ) ;
248 fontSize = 9 ;
249 fontStyle = normal ;
11e62fe6 250#endif
2646f485
SC
251 SetFont( wxFont (fontSize, wxSWISS, wxNORMAL, wxNORMAL , false , wxMacMakeStringFromPascal( fontName ) ) ) ;
252#if TARGET_CARBON
253 Size asize;
254
255
256 CreateListBoxControl( MAC_WXHWND(parent->MacGetRootWindow()), &bounds, false, 0, 1, (style & wxLB_HSCROLL), true,
257 kwxMacListItemHeight, kwxMacListItemHeight, false, &listDef, (ControlRef *)&m_macControl );
258
259 GetControlData( (ControlHandle) m_macControl, kControlNoPart, kControlListBoxListHandleTag,
260 sizeof(ListHandle), (Ptr) &m_macList, &asize);
261
262 SetControlReference( (ControlHandle) m_macControl, (long) this);
263 SetControlVisibility( (ControlHandle) m_macControl, false, false);
264
265#else
266
267 long result ;
268 wxStAppResource resload ;
6bc3b8e9 269 m_macControl = (WXWidget) ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false ,
11e62fe6 270 (style & wxLB_HSCROLL) ? kwxMacListWithVerticalAndHorizontalScrollbar : kwxMacListWithVerticalScrollbar ,
2646f485
SC
271 0 , 0, kControlListBoxProc , (long) this ) ;
272 ::GetControlData( (ControlHandle) m_macControl , kControlNoPart , kControlListBoxListHandleTag ,
273 sizeof( ListHandle ) , (char*) &m_macList , &result ) ;
274
275 HLock( (Handle) m_macList ) ;
276 ldefHandle ldef ;
277 ldef = (ldefHandle) NewHandle( sizeof(ldefRec) ) ;
278 if ( (**(ListHandle)m_macList).listDefProc != NULL )
279 {
280 (**ldef).instruction = 0x4EF9; /* JMP instruction */
281 (**ldef).function = (void(*)()) listDef.u.userProc;
282 (**(ListHandle)m_macList).listDefProc = (Handle) ldef ;
283 }
284
285 Point pt = (**(ListHandle)m_macList).cellSize ;
286 pt.v = kwxMacListItemHeight ;
287 LCellSize( pt , (ListHandle)m_macList ) ;
288 LAddColumn( 1 , 0 , (ListHandle)m_macList ) ;
289#endif
290 OptionBits options = 0;
291 if ( style & wxLB_MULTIPLE )
292 {
293 options += lExtendDrag + lUseSense ;
294 }
295 else if ( style & wxLB_EXTENDED )
296 {
297 // default behaviour
298 }
299 else
300 {
301 options = (OptionBits) lOnlyOne ;
302 }
303 SetListSelectionFlags((ListHandle)m_macList, options);
304
305 for ( int i = 0 ; i < n ; i++ )
306 {
307 Append( choices[i] ) ;
308 }
309
310 MacPostControlCreate() ;
311
312 LSetDrawingMode( true , (ListHandle)m_macList ) ;
313
8228b893 314 return true;
2646f485
SC
315}
316
317wxListBox::~wxListBox()
318{
319 FreeData() ;
320 // avoid access during destruction
321 SetControlReference( (ControlHandle) m_macControl , NULL ) ;
322 if ( m_macList )
323 {
324#if !TARGET_CARBON
325 DisposeHandle( (**(ListHandle)m_macList).listDefProc ) ;
326 (**(ListHandle)m_macList).listDefProc = NULL ;
327#endif
328 m_macList = NULL ;
329 }
330}
331
332void wxListBox::FreeData()
333{
334#if wxUSE_OWNER_DRAWN
335 if ( m_windowStyle & wxLB_OWNERDRAW )
336 {
337 size_t uiCount = m_aItems.Count();
338 while ( uiCount-- != 0 ) {
339 delete m_aItems[uiCount];
340 m_aItems[uiCount] = NULL;
341 }
342
343 m_aItems.Clear();
344 }
345 else
346#endif // wxUSE_OWNER_DRAWN
347 if ( HasClientObjectData() )
348 {
aa61d352 349 for ( unsigned int n = 0; n < m_noItems; n++ )
2646f485
SC
350 {
351 delete GetClientObject(n);
352 }
353 }
354}
355
356void wxListBox::DoSetSize(int x, int y,
357 int width, int height,
358 int sizeFlags )
359{
360 wxControl::DoSetSize( x , y , width , height , sizeFlags ) ;
361#if TARGET_CARBON
362 Rect bounds ;
363 GetControlBounds( (ControlHandle) m_macControl , &bounds ) ;
364 ControlRef control = GetListVerticalScrollBar( (ListHandle)m_macList ) ;
365 if ( control )
366 {
367 Rect scrollbounds ;
368 GetControlBounds( control , &scrollbounds ) ;
369 if( scrollbounds.right != bounds.right + 1 )
370 {
371 UMAMoveControl( control , bounds.right - (scrollbounds.right - scrollbounds.left) + 1 ,
372 scrollbounds.top ) ;
373 }
374 }
375#endif
376}
377void wxListBox::DoSetFirstItem(int N)
378{
379 MacScrollTo( N ) ;
380}
381
aa61d352 382void wxListBox::Delete(unsigned int n)
2646f485 383{
aa61d352 384 wxCHECK_RET( IsValid(n),
2646f485
SC
385 wxT("invalid index in wxListBox::Delete") );
386
387#if wxUSE_OWNER_DRAWN
aa61d352
VZ
388 delete m_aItems[n];
389 m_aItems.RemoveAt(n);
2646f485
SC
390#else // !wxUSE_OWNER_DRAWN
391 if ( HasClientObjectData() )
392 {
aa61d352 393 delete GetClientObject(n);
2646f485
SC
394 }
395#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
aa61d352
VZ
396 m_stringArray.RemoveAt(n) ;
397 m_dataArray.RemoveAt(n) ;
398 m_noItems--;
2646f485 399
aa61d352 400 MacDelete(n) ;
2646f485
SC
401}
402
403int wxListBox::DoAppend(const wxString& item)
404{
9f884528
RD
405 InvalidateBestSize();
406
aa61d352 407 unsigned int index = m_noItems ;
2646f485
SC
408 m_stringArray.Add( item ) ;
409 m_dataArray.Add( NULL );
410 m_noItems ++;
411 DoSetItemClientData( index , NULL ) ;
412 MacAppend( item ) ;
413
414 return index ;
415}
416
417void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
418{
419 MacSetRedraw( false ) ;
420 Clear() ;
421 int n = choices.GetCount();
11e62fe6 422
2646f485
SC
423 for( int i = 0 ; i < n ; ++i )
424 {
425 if ( clientData )
426 {
427#if wxUSE_OWNER_DRAWN
428 wxASSERT_MSG(clientData[i] == NULL,
429 wxT("Can't use client data with owner-drawn listboxes"));
430#else // !wxUSE_OWNER_DRAWN
431 Append( choices[i] , clientData[i] ) ;
432#endif
433 }
434 else
435 Append( choices[i] ) ;
436 }
11e62fe6 437
2646f485
SC
438#if wxUSE_OWNER_DRAWN
439 if ( m_windowStyle & wxLB_OWNERDRAW ) {
440 // first delete old items
aa61d352 441 unsigned int ui = m_aItems.Count();
2646f485
SC
442 while ( ui-- != 0 ) {
443 delete m_aItems[ui];
444 m_aItems[ui] = NULL;
445 }
446 m_aItems.Empty();
11e62fe6 447
2646f485 448 // then create new ones
8228b893 449 for ( ui = 0; ui < m_noItems; ui++ ) {
2646f485
SC
450 wxOwnerDrawn *pNewItem = CreateItem(ui);
451 pNewItem->SetName(choices[ui]);
452 m_aItems.Add(pNewItem);
453 }
454 }
455#endif // wxUSE_OWNER_DRAWN
456 MacSetRedraw( true ) ;
457}
458
459bool wxListBox::HasMultipleSelection() const
460{
461 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
462}
463
11e62fe6 464int wxListBox::FindString(const wxString& s, bool bCase) const
2646f485 465{
2646f485
SC
466 if ( s.Right(1) == wxT("*") )
467 {
8228b893
WS
468 wxString search = s.Left( s.length() - 1 ) ;
469 int len = search.length() ;
2646f485
SC
470 Str255 s1 , s2 ;
471 wxMacStringToPascal( search , s2 ) ;
11e62fe6 472
aa61d352 473 for ( unsigned int i = 0 ; i < m_noItems ; ++ i )
2646f485 474 {
11e62fe6 475 wxMacStringToPascal( m_stringArray[i].Left( len ) , s1 ) ;
2646f485 476
11e62fe6 477 if ( EqualString( s1 , s2 , bCase , false ) )
8228b893 478 return (int)i ;
2646f485 479 }
8228b893 480 if ( s.Left(1) == wxT("*") && s.length() > 1 )
2646f485
SC
481 {
482 wxString st = s ;
483 st.MakeLower() ;
aa61d352 484 for ( unsigned int i = 0 ; i < m_noItems ; ++i )
2646f485 485 {
aa61d352 486 if (GetString(i).Lower().Matches(st))
8228b893 487 return (int)i ;
2646f485
SC
488 }
489 }
11e62fe6 490
2646f485
SC
491 }
492 else
493 {
494 Str255 s1 , s2 ;
11e62fe6 495
2646f485 496 wxMacStringToPascal( s , s2 ) ;
11e62fe6 497
aa61d352 498 for ( unsigned int i = 0 ; i < m_noItems ; ++ i )
2646f485 499 {
11e62fe6 500 wxMacStringToPascal( m_stringArray[i] , s1 ) ;
2646f485 501
11e62fe6 502 if ( EqualString( s1 , s2 , bCase , false ) )
8228b893 503 return (int)i ;
2646f485
SC
504 }
505 }
11e62fe6
WS
506
507 return wxNOT_FOUND;
2646f485
SC
508}
509
510void wxListBox::Clear()
511{
512 FreeData();
513 m_noItems = 0;
514 m_stringArray.Empty() ;
515 m_dataArray.Empty() ;
516 MacClear() ;
517}
518
c6179a84 519void wxListBox::DoSetSelection(int N, bool select)
2646f485 520{
8228b893 521 wxCHECK_RET( IsValid(N),
2646f485
SC
522 wxT("invalid index in wxListBox::SetSelection") );
523 MacSetSelection( N , select ) ;
524 GetSelections( m_selectionPreImage ) ;
525}
526
527bool wxListBox::IsSelected(int N) const
528{
8228b893 529 wxCHECK_MSG( IsValid(N), false,
2646f485 530 wxT("invalid index in wxListBox::Selected") );
11e62fe6 531
2646f485
SC
532 return MacIsSelected( N ) ;
533}
534
aa61d352 535void *wxListBox::DoGetItemClientData(unsigned int n) const
2646f485 536{
aa61d352 537 wxCHECK_MSG( IsValid(n), NULL,
2646f485 538 wxT("invalid index in wxListBox::GetClientData"));
11e62fe6 539
aa61d352 540 return (void *)m_dataArray[n];
2646f485
SC
541}
542
aa61d352 543wxClientData *wxListBox::DoGetItemClientObject(unsigned int n) const
2646f485 544{
aa61d352 545 return (wxClientData *) DoGetItemClientData( n ) ;
2646f485
SC
546}
547
aa61d352 548void wxListBox::DoSetItemClientData(unsigned int n, void *Client_data)
2646f485 549{
aa61d352 550 wxCHECK_RET( IsValid(n),
2646f485 551 wxT("invalid index in wxListBox::SetClientData") );
11e62fe6 552
2646f485
SC
553#if wxUSE_OWNER_DRAWN
554 if ( m_windowStyle & wxLB_OWNERDRAW )
555 {
556 // client data must be pointer to wxOwnerDrawn, otherwise we would crash
557 // in OnMeasure/OnDraw.
558 wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
559 }
560#endif // wxUSE_OWNER_DRAWN
aa61d352 561 wxASSERT_MSG( m_dataArray.GetCount() >= (unsigned int) n , wxT("invalid client_data array") ) ;
11e62fe6 562
aa61d352 563 if ( m_dataArray.GetCount() > (size_t) n )
2646f485 564 {
aa61d352 565 m_dataArray[n] = (char*) Client_data ;
2646f485
SC
566 }
567 else
568 {
569 m_dataArray.Add( (char*) Client_data ) ;
570 }
571}
572
aa61d352 573void wxListBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
2646f485
SC
574{
575 DoSetItemClientData(n, clientData);
576}
577
578// Return number of selections and an array of selected integers
579int wxListBox::GetSelections(wxArrayInt& aSelections) const
580{
581 return MacGetSelections( aSelections ) ;
582}
583
584// Get single selection, for single choice list items
585int wxListBox::GetSelection() const
586{
587 return MacGetSelection() ;
588}
589
590// Find string for position
aa61d352 591wxString wxListBox::GetString(unsigned int n) const
2646f485 592{
aa61d352 593 return m_stringArray[n] ;
2646f485
SC
594}
595
aa61d352 596void wxListBox::DoInsertItems(const wxArrayString& items, unsigned int pos)
2646f485 597{
8228b893 598 wxCHECK_RET( IsValidInsert(pos),
2646f485 599 wxT("invalid index in wxListBox::InsertItems") );
11e62fe6 600
9f884528
RD
601 InvalidateBestSize();
602
aa61d352 603 unsigned int nItems = items.GetCount();
11e62fe6 604
aa61d352 605 for ( unsigned int i = 0 ; i < nItems ; i++ )
2646f485
SC
606 {
607 m_stringArray.Insert( items[i] , pos + i ) ;
608 m_dataArray.Insert( NULL , pos + i ) ;
609 MacInsert( pos + i , items[i] ) ;
610 }
11e62fe6 611
2646f485
SC
612 m_noItems += nItems;
613}
614
aa61d352 615void wxListBox::SetString(unsigned int n, const wxString& s)
2646f485 616{
aa61d352
VZ
617 m_stringArray[n] = s;
618 MacSet(n, s);
2646f485
SC
619}
620
621wxSize wxListBox::DoGetBestSize() const
622{
623 int lbWidth = 100; // some defaults
624 int lbHeight = 110;
625 int wLine;
11e62fe6 626
2646f485 627 {
11e62fe6
WS
628 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetRootWindow() ) ) ;
629
2646f485
SC
630 if ( m_font.Ok() )
631 {
632 ::TextFont( m_font.GetMacFontNum() ) ;
633 ::TextSize( m_font.GetMacFontSize() ) ;
634 ::TextFace( m_font.GetMacFontStyle() ) ;
635 }
636 else
637 {
638 ::TextFont( kFontIDMonaco ) ;
639 ::TextSize( 9 );
640 ::TextFace( 0 ) ;
641 }
11e62fe6 642
2646f485 643 // Find the widest line
aa61d352 644 for(unsigned int i = 0; i < GetCount(); i++) {
2646f485
SC
645 wxString str(GetString(i));
646 #if wxUSE_UNICODE
647 Point bounds={0,0} ;
648 SInt16 baseline ;
649 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) ,
650 kThemeCurrentPortFont,
651 kThemeStateActive,
652 false,
653 &bounds,
654 &baseline );
655 wLine = bounds.h ;
656 #else
8228b893 657 wLine = ::TextWidth( str.c_str() , 0 , str.length() ) ;
2646f485
SC
658 #endif
659 lbWidth = wxMax(lbWidth, wLine);
660 }
11e62fe6 661
2646f485
SC
662 // Add room for the scrollbar
663 lbWidth += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
11e62fe6 664
2646f485
SC
665 // And just a bit more
666 int cy = 12 ;
667 int cx = ::TextWidth( "X" , 0 , 1 ) ;
668 lbWidth += cx ;
11e62fe6 669
2646f485
SC
670 // don't make the listbox too tall (limit height to around 10 items) but don't
671 // make it too small neither
672 lbHeight = (cy+4) * wxMin(wxMax(GetCount(), 3), 10);
673 }
674 return wxSize(lbWidth, lbHeight);
675}
676
aa61d352 677unsigned int wxListBox::GetCount() const
2646f485
SC
678{
679 return m_noItems;
680}
681
682void wxListBox::SetupColours()
683{
684 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
685 SetForegroundColour(GetParent()->GetForegroundColour());
686}
687
688void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
689{
690 wxControl::Refresh( eraseBack , rect ) ;
691 // MacRedrawControl() ;
692}
693
694#if wxUSE_OWNER_DRAWN
695
696class wxListBoxItem : public wxOwnerDrawn
697{
698public:
11e62fe6 699 wxListBoxItem(const wxString& str = wxEmptyString);
2646f485
SC
700};
701
8228b893 702wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, false)
2646f485
SC
703{
704 // no bitmaps/checkmarks
705 SetMarginWidth(0);
706}
707
708wxOwnerDrawn *wxListBox::CreateItem(size_t n)
709{
710 return new wxListBoxItem();
711}
712
713#endif //USE_OWNER_DRAWN
714
715// ============================================================================
716// list box control implementation
717// ============================================================================
718
719/*
720void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon)
721{
722wxListBox* list;
723// typecast our refCon
724list = (wxListBox*)refCon;
725
726 MoveTo(cellRect->left + 4 , cellRect->top + 10 );
727 const wxString text = list->m_stringArray[lCell.v] ;
728 ::TextFont( kFontIDMonaco ) ;
729 ::TextSize( 9 );
730 ::TextFace( 0 ) ;
8228b893 731 DrawText(text, 0 , text.length());
11e62fe6 732
2646f485
SC
733 }
734*/
735void wxListBox::MacDelete( int N )
736{
737 LDelRow( 1 , N , (ListHandle)m_macList) ;
738 Refresh();
739}
740
741void wxListBox::MacInsert( int n , const wxString& text)
742{
743 Cell cell = { 0 , 0 } ;
744 cell.v = n ;
745 LAddRow( 1 , cell.v , (ListHandle)m_macList ) ;
746 // LSetCell(text, strlen(text), cell, m_macList);
747 Refresh();
748}
749
750void wxListBox::MacAppend( const wxString& text)
751{
752 Cell cell = { 0 , 0 } ;
753 cell.v = (**(ListHandle)m_macList).dataBounds.bottom ;
754 LAddRow( 1 , cell.v , (ListHandle)m_macList ) ;
755 // LSetCell(text, strlen(text), cell, m_macList);
756 Refresh();
757}
758
759void wxListBox::MacClear()
760{
761 LDelRow( (**(ListHandle)m_macList).dataBounds.bottom , 0 ,(ListHandle) m_macList ) ;
762 Refresh();
763}
764
765void wxListBox::MacSetSelection( int n , bool select )
766{
767 Cell cell = { 0 , 0 } ;
768 if ( ! (m_windowStyle & wxLB_MULTIPLE) )
769 {
770 if ( LGetSelect( true , &cell , (ListHandle)m_macList ) )
771 {
772 LSetSelect( false , cell , (ListHandle)m_macList ) ;
773 }
774 }
11e62fe6 775
2646f485
SC
776 cell.v = n ;
777 LSetSelect( select , cell , (ListHandle)m_macList ) ;
778 LAutoScroll( (ListHandle)m_macList ) ;
779 Refresh();
780}
781
782bool wxListBox::MacIsSelected( int n ) const
783{
784 Cell cell = { 0 , 0 } ;
785 cell.v = n ;
786 return LGetSelect( false , &cell , (ListHandle)m_macList ) ;
787}
788
789void wxListBox::MacDestroy()
790{
791 // DisposeExtLDEFInfo( m_macList ) ;
792}
793
794int wxListBox::MacGetSelection() const
795{
796 Cell cell = { 0 , 0 } ;
797 if ( LGetSelect( true , &cell , (ListHandle)m_macList ) )
798 return cell.v ;
799 else
800 return -1 ;
801}
802
803int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
804{
805 int no_sel = 0 ;
11e62fe6 806
2646f485 807 aSelections.Empty();
11e62fe6 808
2646f485
SC
809 Cell cell = { 0 , 0 } ;
810 cell.v = 0 ;
11e62fe6 811
2646f485
SC
812 while ( LGetSelect( true , &cell ,(ListHandle) m_macList ) )
813 {
814 aSelections.Add( cell.v ) ;
815 no_sel++ ;
816 cell.v++ ;
817 }
818 return no_sel ;
819}
820
821void wxListBox::MacSet( int n , const wxString& text )
822{
823 // our implementation does not store anything in the list
824 // so we just have to redraw
825 Cell cell = { 0 , 0 } ;
826 cell.v = n ;
827 // LSetCell(text, strlen(text), cell, m_macList);
828 Refresh();
829}
830
831void wxListBox::MacScrollTo( int n )
832{
833 // TODO implement scrolling
834}
835
836void wxListBox::OnSize( wxSizeEvent &event)
837{
838 Point pt;
11e62fe6 839
2646f485
SC
840#if TARGET_CARBON
841 GetListCellSize((ListHandle)m_macList, &pt);
842#else
843 pt = (**(ListHandle)m_macList).cellSize ;
844#endif
845 pt.h = m_width - 15 ;
846 LCellSize( pt , (ListHandle)m_macList ) ;
847}
848
849void wxListBox::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED(mouseStillDown))
850{
851 Boolean wasDoubleClick = false ;
852 long result ;
11e62fe6 853
2646f485
SC
854 ::GetControlData( (ControlHandle) m_macControl , kControlNoPart , kControlListBoxDoubleClickTag , sizeof( wasDoubleClick ) , (char*) &wasDoubleClick , &result ) ;
855 if ( !wasDoubleClick )
856 {
857 MacDoClick() ;
858 }
859 else
860 {
861 MacDoDoubleClick() ;
862 }
863}
864
865void wxListBox::MacSetRedraw( bool doDraw )
866{
867 LSetDrawingMode( doDraw , (ListHandle)m_macList ) ;
2646f485
SC
868}
869
870void wxListBox::MacDoClick()
871{
872 wxArrayInt aSelections;
873 int n ;
874 size_t count = GetSelections(aSelections);
11e62fe6 875
2646f485
SC
876 if ( count == m_selectionPreImage.GetCount() )
877 {
878 bool hasChanged = false ;
879 for ( size_t i = 0 ; i < count ; ++i )
880 {
881 if ( aSelections[i] != m_selectionPreImage[i] )
882 {
883 hasChanged = true ;
884 break ;
885 }
886 }
887 if ( !hasChanged )
888 {
889 return ;
890 }
891 }
11e62fe6 892
2646f485 893 m_selectionPreImage = aSelections;
11e62fe6 894
2646f485
SC
895 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
896 event.SetEventObject( this );
11e62fe6 897
2646f485
SC
898 if ( count > 0 )
899 {
900 n = aSelections[0];
901 if ( HasClientObjectData() )
902 event.SetClientObject( GetClientObject(n) );
903 else if ( HasClientUntypedData() )
904 event.SetClientData( GetClientData(n) );
aa61d352 905 event.SetString(GetString(n));
2646f485
SC
906 }
907 else
908 {
909 n = -1;
910 }
11e62fe6 911
687706f5 912 event.SetInt(n);
11e62fe6 913
2646f485
SC
914 GetEventHandler()->ProcessEvent(event);
915}
916
917void wxListBox::MacDoDoubleClick()
918{
919 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
920 event.SetEventObject( this );
921 GetEventHandler()->ProcessEvent(event) ;
922}
923
924void wxListBox::OnChar(wxKeyEvent& event)
925{
926 if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER)
927 {
928 wxWindow* parent = GetParent() ;
929 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL )
930 parent = parent->GetParent() ;
11e62fe6 931
2646f485
SC
932 if ( parent && parent->GetDefaultItem() )
933 {
934 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
935 wxButton);
936 if ( def && def->IsEnabled() )
937 {
938 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
939 event.SetEventObject(def);
940 def->Command(event);
941 return ;
942 }
943 }
944 event.Skip() ;
945 }
946 /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
947 else if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == '.' && event.MetaDown() ) )
948 {
11e62fe6 949 // FIXME: look in ancestors, not just parent.
2646f485
SC
950 wxWindow* win = GetParent()->FindWindow( wxID_CANCEL ) ;
951 if (win)
952 {
11e62fe6
WS
953 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
954 new_event.SetEventObject( win );
955 win->GetEventHandler()->ProcessEvent( new_event );
956 }
2646f485
SC
957 }
958 else if ( event.GetKeyCode() == WXK_TAB )
959 {
960 wxNavigationKeyEvent new_event;
961 new_event.SetEventObject( this );
962 new_event.SetDirection( !event.ShiftDown() );
963 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
964 new_event.SetWindowChange( event.ControlDown() );
965 new_event.SetCurrentFocus( this );
966 if ( !GetEventHandler()->ProcessEvent( new_event ) )
967 event.Skip() ;
968 }
969 else if ( event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_UP )
970 {
971 // perform the default key handling first
972 wxControl::OnKeyDown( event ) ;
11e62fe6 973
2646f485
SC
974 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
975 event.SetEventObject( this );
11e62fe6 976
2646f485
SC
977 wxArrayInt aSelections;
978 int n, count = GetSelections(aSelections);
979 if ( count > 0 )
980 {
981 n = aSelections[0];
982 if ( HasClientObjectData() )
983 event.SetClientObject( GetClientObject(n) );
984 else if ( HasClientUntypedData() )
985 event.SetClientData( GetClientData(n) );
aa61d352 986 event.SetString(GetString(n));
2646f485
SC
987 }
988 else
989 {
990 n = -1;
991 }
11e62fe6 992
687706f5 993 event.SetInt(n);
11e62fe6 994
2646f485
SC
995 GetEventHandler()->ProcessEvent(event);
996 }
997 else
998 {
999 if ( event.GetTimestamp() > m_lastTypeIn + 60 )
1000 {
1001 m_typeIn = wxEmptyString ;
1002 }
1003 m_lastTypeIn = event.GetTimestamp() ;
1004 m_typeIn += (char) event.GetKeyCode() ;
1005 int line = FindString(wxT("*")+m_typeIn+wxT("*")) ;
1006 if ( line >= 0 )
1007 {
1008 if ( GetSelection() != line )
1009 {
1010 SetSelection(line) ;
1011 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
1012 event.SetEventObject( this );
11e62fe6 1013
2646f485
SC
1014 if ( HasClientObjectData() )
1015 event.SetClientObject( GetClientObject( line ) );
1016 else if ( HasClientUntypedData() )
1017 event.SetClientData( GetClientData(line) );
aa61d352 1018 event.SetString(GetString(line));
11e62fe6 1019
687706f5 1020 event.SetInt(line);
11e62fe6 1021
2646f485
SC
1022 GetEventHandler()->ProcessEvent(event);
1023 }
1024 }
1025 }
1026}
8228b893
WS
1027
1028#endif // wxUSE_LISTBOX