]> git.saurik.com Git - wxWidgets.git/blob - src/mac/classic/listbox.cpp
Make wxRegEx::Replace run in linear time
[wxWidgets.git] / src / mac / classic / listbox.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/listbox.cpp
3 // Purpose: wxListBox
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
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
22 IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
23
24 BEGIN_EVENT_TABLE(wxListBox, wxControl)
25 EVT_SIZE( wxListBox::OnSize )
26 EVT_CHAR( wxListBox::OnChar )
27 END_EVENT_TABLE()
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
39 typedef 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
53 const short kwxMacListItemHeight = 19 ;
54 #else
55 const short kwxMacListItemHeight = 14 ;
56 #endif
57
58 extern "C"
59 {
60 static pascal void wxMacListDefinition( short message, Boolean isSelected, Rect *drawRect,
61 Cell cell, short dataOffset, short dataLength,
62 ListHandle listHandle ) ;
63 }
64
65 static 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 ;
73
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
82
83 // Calculate the cell rect.
84
85 switch( message ) {
86 case lInitMsg:
87 break;
88
89 case lCloseMsg:
90 break;
91
92 case lDrawMsg:
93 {
94 const wxString linetext = list->m_stringArray[cell.v] ;
95
96 // Save the current clip region, and set the clip region to the area we are about
97 // to draw.
98
99 savedClipRegion = NewRgn();
100 GetClip( savedClipRegion );
101
102 ClipRect( drawRect );
103 EraseRect( drawRect );
104
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 }
118
119 #if TARGET_CARBON
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 }
134 #else
135 {
136 wxCharBuffer text = linetext.mb_str( wxConvLocal) ;
137 MoveTo(drawRect->left + 4 , drawRect->top + 10 );
138 DrawText(text, 0 , strlen(text) );
139 }
140 #endif
141 // If the cell is hilited, do the hilite now. Paint the cell contents with the
142 // appropriate QuickDraw transform mode.
143
144 if( isSelected ) {
145 savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
146 SetPortPenMode( (CGrafPtr)grafPtr, hilitetransfermode );
147 PaintRect( drawRect );
148 SetPortPenMode( (CGrafPtr)grafPtr, savedPenMode );
149 }
150
151 // Restore the saved clip region.
152
153 SetClip( savedClipRegion );
154 DisposeRgn( savedClipRegion );
155 }
156 break;
157 case lHiliteMsg:
158
159 // Hilite or unhilite the cell. Paint the cell contents with the
160 // appropriate QuickDraw transform mode.
161
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
174 extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
175 // resources ldef ids
176 const short kwxMacListWithVerticalScrollbar = 128 ;
177 const short kwxMacListWithVerticalAndHorizontalScrollbar = 129 ;
178
179 // ============================================================================
180 // list box control implementation
181 // ============================================================================
182
183 // Listbox item
184 wxListBox::wxListBox()
185 {
186 m_noItems = 0;
187 m_selected = 0;
188 m_macList = NULL ;
189 }
190
191 static ListDefUPP macListDefUPP = NULL ;
192
193 bool 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
207 bool 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 ;
223
224 MacPreControlCreate( parent , id , wxEmptyString , pos , size ,style, validator , name , &bounds , title ) ;
225
226 ListDefSpec listDef;
227 listDef.defType = kListDefUserProcType;
228 if ( macListDefUPP == NULL )
229 {
230 macListDefUPP = NewListDefUPP( wxMacListDefinition );
231 }
232 listDef.u.userProc = macListDefUPP ;
233
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 ;
243 #endif
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 ;
262 m_macControl = (WXWidget) ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false ,
263 (style & wxLB_HSCROLL) ? kwxMacListWithVerticalAndHorizontalScrollbar : kwxMacListWithVerticalScrollbar ,
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
310 wxListBox::~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
325 void 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
349 void 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 }
370 void wxListBox::DoSetFirstItem(int N)
371 {
372 MacScrollTo( N ) ;
373 }
374
375 void 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
396 int wxListBox::DoAppend(const wxString& item)
397 {
398 InvalidateBestSize();
399
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
410 void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
411 {
412 MacSetRedraw( false ) ;
413 Clear() ;
414 int n = choices.GetCount();
415
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 }
430
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();
440
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
452 bool wxListBox::HasMultipleSelection() const
453 {
454 return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
455 }
456
457 int wxListBox::FindString(const wxString& s, bool bCase) const
458 {
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 ) ;
465
466 for ( int i = 0 ; i < m_noItems ; ++ i )
467 {
468 wxMacStringToPascal( m_stringArray[i].Left( len ) , s1 ) ;
469
470 if ( EqualString( s1 , s2 , bCase , false ) )
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 }
483
484 }
485 else
486 {
487 Str255 s1 , s2 ;
488
489 wxMacStringToPascal( s , s2 ) ;
490
491 for ( int i = 0 ; i < m_noItems ; ++ i )
492 {
493 wxMacStringToPascal( m_stringArray[i] , s1 ) ;
494
495 if ( EqualString( s1 , s2 , bCase , false ) )
496 return i ;
497 }
498 }
499
500 return wxNOT_FOUND;
501 }
502
503 void wxListBox::Clear()
504 {
505 FreeData();
506 m_noItems = 0;
507 m_stringArray.Empty() ;
508 m_dataArray.Empty() ;
509 MacClear() ;
510 }
511
512 void wxListBox::DoSetSelection(int N, bool select)
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
520 bool wxListBox::IsSelected(int N) const
521 {
522 wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
523 wxT("invalid index in wxListBox::Selected") );
524
525 return MacIsSelected( N ) ;
526 }
527
528 void *wxListBox::DoGetItemClientData(int N) const
529 {
530 wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
531 wxT("invalid index in wxListBox::GetClientData"));
532
533 return (void *)m_dataArray[N];
534 }
535
536 wxClientData *wxListBox::DoGetItemClientObject(int N) const
537 {
538 return (wxClientData *) DoGetItemClientData( N ) ;
539 }
540
541 void wxListBox::DoSetItemClientData(int N, void *Client_data)
542 {
543 wxCHECK_RET( N >= 0 && N < m_noItems,
544 wxT("invalid index in wxListBox::SetClientData") );
545
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") ) ;
555
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
566 void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
567 {
568 DoSetItemClientData(n, clientData);
569 }
570
571 // Return number of selections and an array of selected integers
572 int wxListBox::GetSelections(wxArrayInt& aSelections) const
573 {
574 return MacGetSelections( aSelections ) ;
575 }
576
577 // Get single selection, for single choice list items
578 int wxListBox::GetSelection() const
579 {
580 return MacGetSelection() ;
581 }
582
583 // Find string for position
584 wxString wxListBox::GetString(int N) const
585 {
586 return m_stringArray[N] ;
587 }
588
589 void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
590 {
591 wxCHECK_RET( pos >= 0 && pos <= m_noItems,
592 wxT("invalid index in wxListBox::InsertItems") );
593
594 InvalidateBestSize();
595
596 int nItems = items.GetCount();
597
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 }
604
605 m_noItems += nItems;
606 }
607
608 void wxListBox::SetString(int N, const wxString& s)
609 {
610 m_stringArray[N] = s ;
611 MacSet( N , s ) ;
612 }
613
614 wxSize wxListBox::DoGetBestSize() const
615 {
616 int lbWidth = 100; // some defaults
617 int lbHeight = 110;
618 int wLine;
619
620 {
621 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetRootWindow() ) ) ;
622
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 }
635
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 }
654
655 // Add room for the scrollbar
656 lbWidth += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
657
658 // And just a bit more
659 int cy = 12 ;
660 int cx = ::TextWidth( "X" , 0 , 1 ) ;
661 lbWidth += cx ;
662
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
670 int wxListBox::GetCount() const
671 {
672 return m_noItems;
673 }
674
675 void wxListBox::SetupColours()
676 {
677 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
678 SetForegroundColour(GetParent()->GetForegroundColour());
679 }
680
681 void wxListBox::Refresh(bool eraseBack, const wxRect *rect)
682 {
683 wxControl::Refresh( eraseBack , rect ) ;
684 // MacRedrawControl() ;
685 }
686
687 #if wxUSE_OWNER_DRAWN
688
689 class wxListBoxItem : public wxOwnerDrawn
690 {
691 public:
692 wxListBoxItem(const wxString& str = wxEmptyString);
693 };
694
695 wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE)
696 {
697 // no bitmaps/checkmarks
698 SetMarginWidth(0);
699 }
700
701 wxOwnerDrawn *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 /*
713 void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon)
714 {
715 wxListBox* list;
716 // typecast our refCon
717 list = (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());
725
726 }
727 */
728 void wxListBox::MacDelete( int N )
729 {
730 LDelRow( 1 , N , (ListHandle)m_macList) ;
731 Refresh();
732 }
733
734 void 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
743 void 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
752 void wxListBox::MacClear()
753 {
754 LDelRow( (**(ListHandle)m_macList).dataBounds.bottom , 0 ,(ListHandle) m_macList ) ;
755 Refresh();
756 }
757
758 void 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 }
768
769 cell.v = n ;
770 LSetSelect( select , cell , (ListHandle)m_macList ) ;
771 LAutoScroll( (ListHandle)m_macList ) ;
772 Refresh();
773 }
774
775 bool 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
782 void wxListBox::MacDestroy()
783 {
784 // DisposeExtLDEFInfo( m_macList ) ;
785 }
786
787 int 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
796 int wxListBox::MacGetSelections( wxArrayInt& aSelections ) const
797 {
798 int no_sel = 0 ;
799
800 aSelections.Empty();
801
802 Cell cell = { 0 , 0 } ;
803 cell.v = 0 ;
804
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
814 void 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
824 void wxListBox::MacScrollTo( int n )
825 {
826 // TODO implement scrolling
827 }
828
829 void wxListBox::OnSize( wxSizeEvent &event)
830 {
831 Point pt;
832
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
842 void wxListBox::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED(mouseStillDown))
843 {
844 Boolean wasDoubleClick = false ;
845 long result ;
846
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
858 void wxListBox::MacSetRedraw( bool doDraw )
859 {
860 LSetDrawingMode( doDraw , (ListHandle)m_macList ) ;
861 }
862
863 void wxListBox::MacDoClick()
864 {
865 wxArrayInt aSelections;
866 int n ;
867 size_t count = GetSelections(aSelections);
868
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 }
885
886 m_selectionPreImage = aSelections;
887
888 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
889 event.SetEventObject( this );
890
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 }
904
905 event.SetInt(n);
906
907 GetEventHandler()->ProcessEvent(event);
908 }
909
910 void wxListBox::MacDoDoubleClick()
911 {
912 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
913 event.SetEventObject( this );
914 GetEventHandler()->ProcessEvent(event) ;
915 }
916
917 void 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() ;
924
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 {
942 // FIXME: look in ancestors, not just parent.
943 wxWindow* win = GetParent()->FindWindow( wxID_CANCEL ) ;
944 if (win)
945 {
946 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
947 new_event.SetEventObject( win );
948 win->GetEventHandler()->ProcessEvent( new_event );
949 }
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 ) ;
966
967 wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
968 event.SetEventObject( this );
969
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 }
985
986 event.SetInt(n);
987
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 );
1006
1007 if ( HasClientObjectData() )
1008 event.SetClientObject( GetClientObject( line ) );
1009 else if ( HasClientUntypedData() )
1010 event.SetClientData( GetClientData(line) );
1011 event.SetString( GetString(line) );
1012
1013 event.SetInt(line);
1014
1015 GetEventHandler()->ProcessEvent(event);
1016 }
1017 }
1018 }
1019 }