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