X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e9576ca53db96b462ed4c0b4bdf47d64c40203e4..e3f9e20cb15c62bd347a8e52d2d36529adbdb3d6:/src/mac/combobox.cpp?ds=sidebyside diff --git a/src/mac/combobox.cpp b/src/mac/combobox.cpp index 0be841bad4..27aa1a58de 100644 --- a/src/mac/combobox.cpp +++ b/src/mac/combobox.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// // Name: combobox.cpp // Purpose: wxComboBox class -// Author: AUTHOR +// Author: Stefan Csomor // Modified by: -// Created: ??/??/98 +// Created: 1998-01-01 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) Stefan Csomor +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ @@ -14,67 +14,374 @@ #endif #include "wx/combobox.h" +#include "wx/button.h" +#include "wx/menu.h" +#include "wx/mac/uma.h" #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl) #endif +// composite combobox implementation by Dan "Bud" Keith bud@otsys.com + + +static int nextPopUpMenuId = 1000 ; +MenuHandle NewUniqueMenu() +{ + MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" ) ; + nextPopUpMenuId++ ; + return handle ; +} + + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the margin between the text control and the choice +static const wxCoord MARGIN = 2; +static const int POPUPWIDTH = 18; +static const int POPUPHEIGHT = 23; + + +// ---------------------------------------------------------------------------- +// wxComboBoxText: text control forwards events to combobox +// ---------------------------------------------------------------------------- + +class wxComboBoxText : public wxTextCtrl +{ +public: + wxComboBoxText( wxComboBox * cb ) + : wxTextCtrl( cb , 1 ) + { + m_cb = cb; + } + +protected: + void OnChar( wxKeyEvent& event ) + { + if ( event.GetKeyCode() == WXK_RETURN ) + { + wxString value = GetValue(); + + if ( m_cb->GetCount() == 0 ) + { + // make Enter generate "selected" event if there is only one item + // in the combobox - without it, it's impossible to select it at + // all! + wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() ); + event.SetInt( 0 ); + event.SetString( value ); + event.SetEventObject( m_cb ); + m_cb->GetEventHandler()->ProcessEvent( event ); + } + else + { + // add the item to the list if it's not there yet + if ( m_cb->FindString(value) == wxNOT_FOUND ) + { + m_cb->Append(value); + m_cb->SetStringSelection(value); + + // and generate the selected event for it + wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() ); + event.SetInt( m_cb->GetCount() - 1 ); + event.SetString( value ); + event.SetEventObject( m_cb ); + m_cb->GetEventHandler()->ProcessEvent( event ); + } + + // This will invoke the dialog default action, such + // as the clicking the default button. + + 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 ; + } + } + + return; + } + } + + event.Skip(); + } + +private: + wxComboBox *m_cb; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl) + EVT_CHAR( wxComboBoxText::OnChar) +END_EVENT_TABLE() + +class wxComboBoxChoice : public wxChoice +{ +public: + wxComboBoxChoice(wxComboBox *cb, int style) + : wxChoice( cb , 1 ) + { + m_cb = cb; + } + +protected: + void OnChoice( wxCommandEvent& e ) + { + wxString s = e.GetString(); + + m_cb->DelegateChoice( s ); + wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() ); + event2.SetInt(m_cb->GetSelection()); + event2.SetEventObject(m_cb); + event2.SetString(m_cb->GetStringSelection()); + m_cb->ProcessCommand(event2); + } + +private: + wxComboBox *m_cb; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice) + EVT_CHOICE(-1, wxComboBoxChoice::OnChoice) +END_EVENT_TABLE() + +wxComboBox::~wxComboBox() +{ + // delete client objects + FreeData(); + + // delete the controls now, don't leave them alive even though they would + // still be eventually deleted by our parent - but it will be too late, the + // user code expects them to be gone now + if (m_text != NULL) { + delete m_text; + m_text = NULL; + } + if (m_choice != NULL) { + delete m_choice; + m_choice = NULL; + } +} + + +// ---------------------------------------------------------------------------- +// geometry +// ---------------------------------------------------------------------------- + +wxSize wxComboBox::DoGetBestSize() const +{ + wxSize size = m_choice->GetBestSize(); + + if ( m_text != NULL ) + { + wxSize sizeText = m_text->GetBestSize(); + + size.x = POPUPWIDTH + sizeText.x + MARGIN; + } + + return size; +} + +void wxComboBox::DoMoveWindow(int x, int y, int width, int height) { + height = POPUPHEIGHT; + + wxControl::DoMoveWindow(x, y, width, height); + + if ( m_text == NULL ) + { + m_choice->SetSize(0, 0 , width, -1); + } + else + { + wxCoord wText = width - POPUPWIDTH - MARGIN; + m_text->SetSize(0, 0, wText, height); + m_choice->SetSize(0 + wText + MARGIN, 0, POPUPWIDTH, -1); + } +} + + + +// ---------------------------------------------------------------------------- +// operations forwarded to the subcontrols +// ---------------------------------------------------------------------------- + +bool wxComboBox::Enable(bool enable) +{ + if ( !wxControl::Enable(enable) ) + return FALSE; + + return TRUE; +} + +bool wxComboBox::Show(bool show) +{ + if ( !wxControl::Show(show) ) + return FALSE; + + return TRUE; +} + +void wxComboBox::SetFocus() +{ + if ( m_text != NULL) { + m_text->SetFocus(); + } +} + + +void wxComboBox::DelegateTextChanged( const wxString& value ) +{ + SetStringSelection( value ); +} + + +void wxComboBox::DelegateChoice( const wxString& value ) +{ + SetStringSelection( value ); +} + + bool wxComboBox::Create(wxWindow *parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, - int n, const wxString choices[], - long style, + const wxArrayString& choices, + long style, const wxValidator& validator, const wxString& name) { - SetName(name); - SetValidator(validator); - m_noStrings = n; - m_windowStyle = style; + wxCArrayString chs( choices ); - if (parent) parent->AddChild(this); + return Create( parent, id, value, pos, size, chs.GetCount(), + chs.GetStrings(), style, validator, name ); +} - if ( id == -1 ) - m_windowId = (int)NewControlId(); - else - m_windowId = id; - // TODO: create combobox control +bool wxComboBox::Create(wxWindow *parent, wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) +{ + if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style , + wxDefaultValidator, name) ) + { + return FALSE; + } + + m_choice = new wxComboBoxChoice(this, style ); + + wxSize csize = size; + if ( style & wxCB_READONLY ) + { + m_text = NULL; + } + else + { + m_text = new wxComboBoxText(this); + if ( size.y == -1 ) { + csize.y = m_text->GetSize().y ; + } + } + + DoSetSize(pos.x, pos.y, csize.x, csize.y); + + for ( int i = 0 ; i < n ; i++ ) + { + m_choice->DoAppend( choices[ i ] ); + } return TRUE; } wxString wxComboBox::GetValue() const { - // TODO - return wxString(""); + wxString result; + + if ( m_text == NULL ) + { + result = m_choice->GetString( m_choice->GetSelection() ); + } + else + { + result = m_text->GetValue(); + } + + return result; } void wxComboBox::SetValue(const wxString& value) { - // TODO + int s = FindString (value); + if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) ) + { + m_choice->Append(value) ; + } + SetStringSelection( value ) ; } // Clipboard operations void wxComboBox::Copy() { - // TODO + if ( m_text != NULL ) + { + m_text->Copy(); + } } void wxComboBox::Cut() { - // TODO + if ( m_text != NULL ) + { + m_text->Cut(); + } } void wxComboBox::Paste() { - // TODO + if ( m_text != NULL ) + { + m_text->Paste(); + } } void wxComboBox::SetEditable(bool editable) { - // TODO + if ( ( m_text == NULL ) && editable ) + { + m_text = new wxComboBoxText( this ); + } + else if ( ( m_text != NULL ) && !editable ) + { + delete m_text; + m_text = NULL; + } + + int currentX, currentY; + GetPosition( ¤tX, ¤tY ); + + int currentW, currentH; + GetSize( ¤tW, ¤tH ); + + DoMoveWindow( currentX, currentY, currentW, currentH ); } void wxComboBox::SetInsertionPoint(long pos) @@ -114,52 +421,120 @@ void wxComboBox::SetSelection(long from, long to) // TODO } -void wxComboBox::Append(const wxString& item) +int wxComboBox::DoAppend(const wxString& item) { - // TODO + return m_choice->DoAppend( item ) ; +} + +int wxComboBox::DoInsert(const wxString& item, int pos) +{ + return m_choice->DoInsert( item , pos ) ; +} + +void wxComboBox::DoSetItemClientData(int n, void* clientData) +{ + return m_choice->DoSetItemClientData( n , clientData ) ; +} + +void* wxComboBox::DoGetItemClientData(int n) const +{ + return m_choice->DoGetItemClientData( n ) ; +} + +void wxComboBox::DoSetItemClientObject(int n, wxClientData* clientData) +{ + return m_choice->DoSetItemClientObject( n , clientData ) ; +} + +wxClientData* wxComboBox::DoGetItemClientObject(int n) const +{ + return m_choice->DoGetItemClientObject( n ) ; +} + +void wxComboBox::FreeData() +{ + if ( HasClientObjectData() ) + { + size_t count = GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + SetClientObject( n, NULL ); + } + } } void wxComboBox::Delete(int n) { - // TODO + // force client object deletion + if( HasClientObjectData() ) + SetClientObject( n, NULL ); + m_choice->Delete( n ); } void wxComboBox::Clear() { - // TODO + FreeData(); + m_choice->Clear(); } int wxComboBox::GetSelection() const { - // TODO - return -1; + return m_choice->GetSelection(); } void wxComboBox::SetSelection(int n) { - // TODO + m_choice->SetSelection( n ); + + if ( m_text != NULL ) + { + m_text->SetValue( GetString( n ) ); + } } int wxComboBox::FindString(const wxString& s) const { - // TODO - return -1; + return m_choice->FindString( s ); } wxString wxComboBox::GetString(int n) const { - // TODO - return wxString(""); + return m_choice->GetString( n ); } wxString wxComboBox::GetStringSelection() const { - // TODO - return wxString(""); + int sel = GetSelection (); + if (sel > -1) + return wxString(this->GetString (sel)); + else + return wxEmptyString; } bool wxComboBox::SetStringSelection(const wxString& sel) { - // TODO - return FALSE; + int s = FindString (sel); + if (s > -1) + { + SetSelection (s); + return TRUE; + } + else + return FALSE; } + +void wxComboBox::SetString(int n, const wxString& s) +{ + m_choice->SetString( n , s ) ; +} + + +void wxComboBox::MacHandleControlClick( WXWidget WXUNUSED(control) , wxInt16 WXUNUSED(controlpart) , bool WXUNUSED(mouseStillDown)) +{ + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId ); + event.SetInt(GetSelection()); + event.SetEventObject(this); + event.SetString(GetStringSelection()); + ProcessCommand(event); +} +