+}
+
+void wxListBox::OnChar(wxKeyEvent& event)
+{
+ // todo trigger proper events here
+ event.Skip() ;
+ return ;
+
+ if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER)
+ {
+ wxWindow* parent = GetParent() ;
+ while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL )
+ parent = parent->GetParent() ;
+
+ if ( parent && parent->GetDefaultItem() )
+ {
+ wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
+ wxButton);
+ if ( def && def->IsEnabled() )
+ {
+ wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
+ event.SetEventObject(def);
+ def->Command(event);
+ return ;
+ }
+ }
+ event.Skip() ;
+ }
+ /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
+ else if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == '.' && event.MetaDown() ) )
+ {
+ // FIXME: look in ancestors, not just parent.
+ wxWindow* win = GetParent()->FindWindow( wxID_CANCEL ) ;
+ if (win)
+ {
+ wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
+ new_event.SetEventObject( win );
+ win->GetEventHandler()->ProcessEvent( new_event );
+ }
+ }
+ else if ( event.GetKeyCode() == WXK_TAB )
+ {
+ wxNavigationKeyEvent new_event;
+ new_event.SetEventObject( this );
+ new_event.SetDirection( !event.ShiftDown() );
+ /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
+ new_event.SetWindowChange( event.ControlDown() );
+ new_event.SetCurrentFocus( this );
+ if ( !GetEventHandler()->ProcessEvent( new_event ) )
+ event.Skip() ;
+ }
+ else if ( event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_UP )
+ {
+ // perform the default key handling first
+ wxControl::OnKeyDown( event ) ;
+
+ wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
+ event.SetEventObject( this );
+
+ wxArrayInt aSelections;
+ int n, count = GetSelections(aSelections);
+ if ( count > 0 )
+ {
+ n = aSelections[0];
+ if ( HasClientObjectData() )
+ event.SetClientObject( GetClientObject(n) );
+ else if ( HasClientUntypedData() )
+ event.SetClientData( GetClientData(n) );
+ event.SetString( GetString(n) );
+ }
+ else
+ {
+ n = -1;
+ }
+
+ event.m_commandInt = n;
+
+ GetEventHandler()->ProcessEvent(event);
+ }
+ else
+ {
+ if ( event.GetTimestamp() > m_lastTypeIn + 60 )
+ {
+ m_typeIn = wxEmptyString ;
+ }
+ m_lastTypeIn = event.GetTimestamp() ;
+ m_typeIn += (char) event.GetKeyCode() ;
+ int line = FindString(wxT("*")+m_typeIn+wxT("*")) ;
+ if ( line >= 0 )
+ {
+ if ( GetSelection() != line )
+ {
+ SetSelection(line) ;
+ wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
+ event.SetEventObject( this );
+
+ if ( HasClientObjectData() )
+ event.SetClientObject( GetClientObject( line ) );
+ else if ( HasClientUntypedData() )
+ event.SetClientData( GetClientData(line) );
+ event.SetString( GetString(line) );
+
+ event.m_commandInt = line ;
+
+ GetEventHandler()->ProcessEvent(event);
+ }
+ }
+ }
+}
+
+#else
+
+// old carbon version
+
+const short kwxMacListItemHeight = 19 ;
+
+extern "C"
+{
+static pascal void wxMacListDefinition( short message, Boolean isSelected, Rect *drawRect,
+ Cell cell, short dataOffset, short dataLength,
+ ListHandle listHandle ) ;
+}
+
+static pascal void wxMacListDefinition( short message, Boolean isSelected, Rect *d,
+ Cell cell, short dataOffset, short dataLength,
+ ListHandle listHandle )
+{
+ wxListBox* list;
+ Rect r = *d ;
+ Rect* drawRect = &r ;
+
+ list = (wxListBox*) GetControlReference( (ControlRef) GetListRefCon(listHandle) );
+ if ( list == NULL || list->GetHandle() == NULL || GetControlReference( ( ControlRef )list->GetHandle() ) == NULL )
+ return ;
+
+ // the bounds passed in are not correct, adjust the right border
+ int x = 0 , y = 0 ;
+ Rect bounds ;
+ GetControlBounds( (ControlRef) list->GetHandle() , &bounds ) ;
+ r.right = r.left + (bounds.right - bounds.left ) - 16 ;
+
+ GrafPtr savePort;
+ GrafPtr grafPtr;
+ RgnHandle savedClipRegion;
+ SInt32 savedPenMode;
+ GetPort(&savePort);
+ SetPort((**listHandle).port);
+ grafPtr = (**listHandle).port ;
+ // typecast our refCon
+
+ // Calculate the cell rect.
+
+ switch( message ) {
+ case lInitMsg:
+ break;
+
+ case lCloseMsg:
+ break;
+
+ case lDrawMsg:
+ {
+ const wxString linetext = list->m_stringArray[cell.v] ;
+
+ // Save the current clip region, and set the clip region to the area we are about
+ // to draw.
+
+ savedClipRegion = NewRgn();
+ GetClip( savedClipRegion );
+
+ ClipRect( drawRect );
+ EraseRect( drawRect );
+
+ const wxFont& font = list->GetFont();
+ if ( font.Ok() )
+ {
+ ::TextFont( font.MacGetFontNum() ) ;
+ ::TextSize( font.MacGetFontSize() ) ;
+ ::TextFace( font.MacGetFontStyle() ) ;
+ }
+ else
+ {
+ ::TextFont( kFontIDMonaco ) ;
+ ::TextSize( 9 );
+ ::TextFace( 0 ) ;
+ }
+
+ {
+ Rect frame = { drawRect->top, drawRect->left + 4,
+ drawRect->top + kwxMacListItemHeight, drawRect->right + 10000 } ;
+ CFMutableStringRef mString = CFStringCreateMutableCopy( NULL , 0 , wxMacCFStringHolder(linetext , list->GetFont().GetEncoding()) ) ;
+ ::TruncateThemeText( mString , kThemeCurrentPortFont, kThemeStateActive, drawRect->right - drawRect->left , truncEnd , NULL ) ;
+
+ ::DrawThemeTextBox( mString,
+ kThemeCurrentPortFont,
+ kThemeStateActive,
+ false,
+ &frame,
+ teJustLeft,
+ nil );
+
+ CFRelease( mString ) ;
+ }
+
+ // If the cell is hilited, do the hilite now. Paint the cell contents with the
+ // appropriate QuickDraw transform mode.
+
+ if( isSelected ) {
+ savedPenMode = GetPortPenMode( (CGrafPtr) grafPtr );
+ SetPortPenMode( (CGrafPtr)grafPtr, hilitetransfermode );
+ PaintRect( drawRect );
+ SetPortPenMode( (CGrafPtr)grafPtr, savedPenMode );
+ }
+
+ // Restore the saved clip region.
+
+ SetClip( savedClipRegion );
+ DisposeRgn( savedClipRegion );
+ }
+ break;
+ case lHiliteMsg:
+
+ // Hilite or unhilite the cell. Paint the cell contents with the
+ // appropriate QuickDraw transform mode.
+
+ GetPort( &grafPtr );
+ savedPenMode = GetPortPenMode( (CGrafPtr)grafPtr );
+ SetPortPenMode( (CGrafPtr)grafPtr, hilitetransfermode );
+ PaintRect( drawRect );
+ SetPortPenMode( (CGrafPtr)grafPtr, savedPenMode );
+ break;
+ default :
+ break ;
+ }
+ SetPort(savePort);
+}
+
+extern "C" void MacDrawStringCell(Rect *cellRect, Cell lCell, ListHandle theList, long refCon) ;
+// resources ldef ids
+const short kwxMacListWithVerticalScrollbar = 128 ;
+const short kwxMacListWithVerticalAndHorizontalScrollbar = 129 ;
+
+// ============================================================================
+// list box control implementation
+// ============================================================================
+
+// Listbox item
+wxListBox::wxListBox()
+{
+ m_noItems = 0;
+ m_selected = 0;
+ m_macList = NULL ;
+}
+
+static ListDefUPP macListDefUPP = NULL ;
+
+bool wxListBox::Create(wxWindow *parent, wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ const wxArrayString& choices,
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ wxCArrayString chs(choices);
+
+ return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(),
+ style, validator, name);
+}
+
+bool wxListBox::Create(wxWindow *parent, wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n, const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ m_macIsUserPane = FALSE ;
+
+ if ( !wxListBoxBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
+ return false;
+
+ m_noItems = 0 ; // this will be increased by our append command
+ m_selected = 0;
+
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
+
+ ListDefSpec listDef;
+ listDef.defType = kListDefUserProcType;
+ if ( macListDefUPP == NULL )
+ {
+ macListDefUPP = NewListDefUPP( wxMacListDefinition );
+ }
+ listDef.u.userProc = macListDefUPP ;
+
+ Str255 fontName ;
+ SInt16 fontSize ;
+ Style fontStyle ;
+
+ GetThemeFont(kThemeViewsFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
+
+ SetFont( wxFont (fontSize, wxSWISS, wxNORMAL, wxNORMAL , false , wxMacMakeStringFromPascal( fontName ) ) ) ;
+
+ Size asize;
+
+
+ CreateListBoxControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds, false, 0, 1, (style & wxLB_HSCROLL), true,
+ kwxMacListItemHeight, kwxMacListItemHeight, false, &listDef, (ControlRef *)&m_macControl );
+
+ GetControlData( (ControlRef) m_macControl, kControlNoPart, kControlListBoxListHandleTag,
+ sizeof(ListHandle), (Ptr) &m_macList, &asize);
+
+ SetControlReference( (ControlRef) m_macControl, (long) this);
+
+
+ OptionBits options = 0;
+ if ( style & wxLB_MULTIPLE )
+ {
+ options += lExtendDrag + lUseSense ;
+ }
+ else if ( style & wxLB_EXTENDED )
+ {
+ // default behaviour
+ }
+ else
+ {
+ options = (OptionBits) lOnlyOne ;
+ }
+ SetListSelectionFlags((ListHandle)m_macList, options);
+
+ for ( int i = 0 ; i < n ; i++ )
+ {
+ Append( choices[i] ) ;
+ }
+
+ MacPostControlCreate(pos,size) ;
+
+ LSetDrawingMode( true , (ListHandle)m_macList ) ;
+
+ return TRUE;
+}
+
+wxListBox::~wxListBox()
+{
+ SetControlReference( (ControlRef) m_macControl , NULL ) ;
+ FreeData() ;
+ // avoid access during destruction
+ if ( m_macList )
+ {
+ m_macList = NULL ;
+ }
+}
+
+void wxListBox::FreeData()
+{
+#if wxUSE_OWNER_DRAWN
+ if ( m_windowStyle & wxLB_OWNERDRAW )
+ {
+ size_t uiCount = m_aItems.Count();
+ while ( uiCount-- != 0 ) {
+ delete m_aItems[uiCount];
+ m_aItems[uiCount] = NULL;
+ }
+
+ m_aItems.Clear();
+ }
+ else
+#endif // wxUSE_OWNER_DRAWN
+ if ( HasClientObjectData() )
+ {
+ for ( size_t n = 0; n < (size_t)m_noItems; n++ )
+ {
+ delete GetClientObject(n);
+ }
+ }
+}
+
+void wxListBox::DoSetSize(int x, int y,
+ int width, int height,
+ int sizeFlags )
+{
+ wxControl::DoSetSize( x , y , width , height , sizeFlags ) ;
+#if TARGET_CARBON
+ Rect bounds ;
+ GetControlBounds( (ControlRef) m_macControl , &bounds ) ;
+ ControlRef control = GetListVerticalScrollBar( (ListHandle)m_macList ) ;
+ if ( control )
+ {
+ Rect scrollbounds ;
+ GetControlBounds( control , &scrollbounds ) ;
+ if( scrollbounds.right != bounds.right + 1 )
+ {
+ UMAMoveControl( control , bounds.right - (scrollbounds.right - scrollbounds.left) + 1 ,
+ scrollbounds.top ) ;
+ }
+ }
+#endif
+}
+void wxListBox::DoSetFirstItem(int N)
+{
+ MacScrollTo( N ) ;
+}
+
+void wxListBox::Delete(int N)
+{
+ wxCHECK_RET( N >= 0 && N < m_noItems,
+ wxT("invalid index in wxListBox::Delete") );
+
+#if wxUSE_OWNER_DRAWN
+ delete m_aItems[N];
+ m_aItems.RemoveAt(N);
+#else // !wxUSE_OWNER_DRAWN
+ if ( HasClientObjectData() )
+ {
+ delete GetClientObject(N);
+ }
+#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
+ m_stringArray.RemoveAt( N ) ;
+ m_dataArray.RemoveAt( N ) ;
+ m_noItems --;
+
+ MacDelete( N ) ;
+}
+
+int wxListBox::DoAppend(const wxString& item)
+{
+ int index = m_noItems ;
+ m_stringArray.Add( item ) ;
+ m_dataArray.Add( NULL );
+ m_noItems ++;
+ DoSetItemClientData( index , NULL ) ;
+ MacAppend( item ) ;
+
+ return index ;
+}
+
+void wxListBox::DoSetItems(const wxArrayString& choices, void** clientData)
+{
+ MacSetRedraw( false ) ;
+ Clear() ;
+ int n = choices.GetCount();
+
+ for( int i = 0 ; i < n ; ++i )
+ {
+ if ( clientData )
+ {
+#if wxUSE_OWNER_DRAWN
+ wxASSERT_MSG(clientData[i] == NULL,
+ wxT("Can't use client data with owner-drawn listboxes"));
+#else // !wxUSE_OWNER_DRAWN
+ Append( choices[i] , clientData[i] ) ;
+#endif
+ }
+ else
+ Append( choices[i] ) ;
+ }
+
+#if wxUSE_OWNER_DRAWN
+ if ( m_windowStyle & wxLB_OWNERDRAW ) {
+ // first delete old items
+ size_t ui = m_aItems.Count();
+ while ( ui-- != 0 ) {
+ delete m_aItems[ui];
+ m_aItems[ui] = NULL;
+ }
+ m_aItems.Empty();
+
+ // then create new ones
+ for ( ui = 0; ui < (size_t)m_noItems; ui++ ) {
+ wxOwnerDrawn *pNewItem = CreateItem(ui);
+ pNewItem->SetName(choices[ui]);
+ m_aItems.Add(pNewItem);
+ }
+ }
+#endif // wxUSE_OWNER_DRAWN
+ MacSetRedraw( true ) ;
+}
+
+bool wxListBox::HasMultipleSelection() const
+{
+ return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
+}
+
+int wxListBox::FindString(const wxString& s) const
+{
+
+ if ( s.Right(1) == wxT("*") )
+ {
+ wxString search = s.Left( s.Length() - 1 ) ;
+ int len = search.Length() ;
+ Str255 s1 , s2 ;
+ wxMacStringToPascal( search , s2 ) ;
+
+ for ( int i = 0 ; i < m_noItems ; ++ i )
+ {
+ wxMacStringToPascal( m_stringArray[i].Left( len ) , s1 ) ;
+
+ if ( EqualString( s1 , s2 , false , false ) )
+ return i ;
+ }
+ if ( s.Left(1) == wxT("*") && s.Length() > 1 )
+ {
+ wxString st = s ;
+ st.MakeLower() ;
+ for ( int i = 0 ; i < m_noItems ; ++i )
+ {
+ if ( GetString(i).Lower().Matches(st) )
+ return i ;
+ }
+ }
+
+ }
+ else
+ {
+ Str255 s1 , s2 ;
+
+ wxMacStringToPascal( s , s2 ) ;
+
+ for ( int i = 0 ; i < m_noItems ; ++ i )
+ {
+ wxMacStringToPascal( m_stringArray[i] , s1 ) ;
+
+ if ( EqualString( s1 , s2 , false , false ) )
+ return i ;
+ }
+ }
+ return -1;
+}
+
+void wxListBox::Clear()
+{
+ FreeData();
+ m_noItems = 0;
+ m_stringArray.Empty() ;
+ m_dataArray.Empty() ;
+ MacClear() ;
+}
+
+void wxListBox::SetSelection(int N, bool select)
+{
+ wxCHECK_RET( N >= 0 && N < m_noItems,
+ wxT("invalid index in wxListBox::SetSelection") );
+ MacSetSelection( N , select ) ;
+ GetSelections( m_selectionPreImage ) ;
+}
+
+bool wxListBox::IsSelected(int N) const
+{
+ wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE,
+ wxT("invalid index in wxListBox::Selected") );
+
+ return MacIsSelected( N ) ;
+}
+
+void *wxListBox::DoGetItemClientData(int N) const
+{
+ wxCHECK_MSG( N >= 0 && N < m_noItems, NULL,
+ wxT("invalid index in wxListBox::GetClientData"));
+
+ return (void *)m_dataArray[N];
+}
+
+wxClientData *wxListBox::DoGetItemClientObject(int N) const
+{
+ return (wxClientData *) DoGetItemClientData( N ) ;
+}
+
+void wxListBox::DoSetItemClientData(int N, void *Client_data)
+{
+ wxCHECK_RET( N >= 0 && N < m_noItems,
+ wxT("invalid index in wxListBox::SetClientData") );
+
+#if wxUSE_OWNER_DRAWN
+ if ( m_windowStyle & wxLB_OWNERDRAW )
+ {
+ // client data must be pointer to wxOwnerDrawn, otherwise we would crash
+ // in OnMeasure/OnDraw.
+ wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
+ }
+#endif // wxUSE_OWNER_DRAWN
+ wxASSERT_MSG( m_dataArray.GetCount() >= (size_t) N , wxT("invalid client_data array") ) ;
+
+ if ( m_dataArray.GetCount() > (size_t) N )
+ {
+ m_dataArray[N] = (char*) Client_data ;
+ }
+ else
+ {
+ m_dataArray.Add( (char*) Client_data ) ;
+ }
+}
+
+void wxListBox::DoSetItemClientObject(int n, wxClientData* clientData)
+{
+ DoSetItemClientData(n, clientData);
+}
+
+// Return number of selections and an array of selected integers
+int wxListBox::GetSelections(wxArrayInt& aSelections) const
+{
+ return MacGetSelections( aSelections ) ;