X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/23645bfa01b6450257f140a30c87565225b1ef4a..ffafd8a55bb0b8fb4236e4522792a6b143813609:/src/univ/combobox.cpp diff --git a/src/univ/combobox.cpp b/src/univ/combobox.cpp index 50cb51feb2..a61d580100 100644 --- a/src/univ/combobox.cpp +++ b/src/univ/combobox.cpp @@ -9,16 +9,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -/* - TODO: - - +1. typing in the text should select the string in listbox - +2. scrollbars in listbox are unusable - +3. the initially selected item is not selected - ?4. kbd interface (what does GTK do?) - 5. there is still autoscrolling without scrollbars - but is it bad? - */ - // ============================================================================ // declarations // ============================================================================ @@ -27,7 +17,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "univcombobox.h" #endif @@ -51,6 +41,7 @@ #include "wx/validate.h" #endif +#include "wx/tooltip.h" #include "wx/popupwin.h" #include "wx/univ/renderer.h" @@ -65,6 +56,12 @@ 3. which passes them to the popup window if it is popped up */ +// constants +// ---------------------------------------------------------------------------- + +// the margin between the text control and the combo button +static const wxCoord g_comboMargin = 2; + // ---------------------------------------------------------------------------- // wxComboButton is just a normal button except that it sends commands to the // combobox and not its parent @@ -96,7 +93,7 @@ public: } protected: - void OnButton(wxCommandEvent& event) { m_combo->ShowPopup(); } + void OnButton(wxCommandEvent& WXUNUSED(event)) { m_combo->ShowPopup(); } virtual wxSize DoGetBestClientSize() const { @@ -126,8 +123,11 @@ public: // implement wxComboPopup methods virtual bool SetSelection(const wxString& value); + virtual void SetSelection(int n, bool select) + { wxListBox::SetSelection( n, select); }; virtual wxControl *GetControl() { return this; } virtual void OnShow(); + virtual wxCoord GetBestWidth() const; protected: // we shouldn't return height too big from here @@ -136,6 +136,9 @@ protected: // filter mouse move events happening outside the list box void OnMouseMove(wxMouseEvent& event); + // set m_clicked value from here + void OnLeftUp(wxMouseEvent& event); + // called whenever the user selects or activates a listbox item void OnSelect(wxCommandEvent& event); @@ -145,6 +148,9 @@ protected: const wxString& strArg); private: + // has the mouse been released on this control? + bool m_clicked; + DECLARE_EVENT_TABLE() }; @@ -183,6 +189,7 @@ BEGIN_EVENT_TABLE(wxComboListBox, wxListBox) EVT_LISTBOX(-1, wxComboListBox::OnSelect) EVT_LISTBOX_DCLICK(-1, wxComboListBox::OnSelect) EVT_MOTION(wxComboListBox::OnMouseMove) + EVT_LEFT_UP(wxComboListBox::OnLeftUp) END_EVENT_TABLE() BEGIN_EVENT_TABLE(wxComboControl, wxControl) @@ -196,7 +203,7 @@ BEGIN_EVENT_TABLE(wxComboTextCtrl, wxTextCtrl) EVT_TEXT(-1, wxComboTextCtrl::OnText) END_EVENT_TABLE() -IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl); +IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl) // ============================================================================ // implementation @@ -285,7 +292,7 @@ wxComboControl::~wxComboControl() // ---------------------------------------------------------------------------- void wxComboControl::DoSetSize(int x, int y, - int width, int height, + int width, int WXUNUSED(height), int sizeFlags) { // combo height is always fixed @@ -296,8 +303,15 @@ wxSize wxComboControl::DoGetBestClientSize() const { wxSize sizeBtn = m_btn->GetBestSize(), sizeText = m_text->GetBestSize(); + wxCoord widthPopup = 0; + + if (m_popup) + { + widthPopup = m_popup->GetBestWidth(); + } - return wxSize(sizeBtn.x + sizeText.x, wxMax(sizeBtn.y, sizeText.y)); + return wxSize(wxMax(sizeText.x + g_comboMargin + sizeBtn.x, widthPopup), + wxMax(sizeBtn.y, sizeText.y)); } void wxComboControl::DoMoveWindow(int x, int y, int width, int height) @@ -314,8 +328,9 @@ void wxComboControl::DoMoveWindow(int x, int y, int width, int height) wxSize sizeBtn = m_btn->GetBestSize(); wxCoord wText = width - sizeBtn.x; - m_text->SetSize(x, y, wText, height); - m_btn->SetSize(x + wText, y, sizeBtn.x, height); + wxPoint p = GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0); + m_text->SetSize(x - p.x, y - p.y, wText, height); + m_btn->SetSize(x - p.x + wText, y - p.y, sizeBtn.x, height); } // ---------------------------------------------------------------------------- @@ -340,13 +355,36 @@ bool wxComboControl::Show(bool show) if (m_btn) m_btn->Show(show); - + if (m_text) m_text->Show(show); return TRUE; } +#if wxUSE_TOOLTIPS +void wxComboControl::DoSetToolTip(wxToolTip *tooltip) +{ + wxControl::DoSetToolTip(tooltip); + + // Set tool tip for button and text box + if (m_text && m_btn) + { + if (tooltip) + { + const wxString &tip = tooltip->GetTip(); + m_text->SetToolTip(tip); + m_btn->SetToolTip(tip); + } + else + { + m_text->SetToolTip(NULL); + m_btn->SetToolTip(NULL); + } + } +} +#endif // wxUSE_TOOLTIPS + // ---------------------------------------------------------------------------- // popup window handling // ---------------------------------------------------------------------------- @@ -381,6 +419,7 @@ void wxComboControl::ShowPopup() m_winPopup->PositionNearCombo(); // show it + m_popup->OnShow(); m_winPopup->Popup(m_text); m_text->SelectAll(); m_popup->SetSelection(m_text->GetValue()); @@ -520,22 +559,28 @@ bool wxComboListBox::SetSelection(const wxString& value) void wxComboListBox::OnSelect(wxCommandEvent& event) { - // first let the user code have the event - - // all fields are already filled by the listbox, just change the event - // type and send it to the combo - wxCommandEvent event2 = event; - event2.SetEventType(wxEVT_COMMAND_COMBOBOX_SELECTED); - event2.SetEventObject(m_combo); - event2.SetId(m_combo->GetId()); - m_combo->ProcessEvent(event2); - - // next update the combo and close the listbox - m_combo->OnSelect(event.GetString()); + if ( m_clicked ) + { + // first update the combo and close the listbox + m_combo->OnSelect(event.GetString()); + + // next let the user code have the event + + // all fields are already filled by the listbox, just change the event + // type and send it to the combo + wxCommandEvent event2 = event; + event2.SetEventType(wxEVT_COMMAND_COMBOBOX_SELECTED); + event2.SetEventObject(m_combo); + event2.SetId(m_combo->GetId()); + m_combo->ProcessEvent(event2); + } + //else: ignore the events resultign from just moving the mouse initially } void wxComboListBox::OnShow() { + // nobody clicked us yet + m_clicked = FALSE; } bool wxComboListBox::PerformAction(const wxControlAction& action, @@ -554,6 +599,14 @@ bool wxComboListBox::PerformAction(const wxControlAction& action, return wxListBox::PerformAction(action, numArg, strArg); } +void wxComboListBox::OnLeftUp(wxMouseEvent& event) +{ + // we should dismiss the combo now + m_clicked = TRUE; + + event.Skip(); +} + void wxComboListBox::OnMouseMove(wxMouseEvent& event) { // while a wxComboListBox is shown, it always has capture, so if it doesn't @@ -572,6 +625,12 @@ void wxComboListBox::OnMouseMove(wxMouseEvent& event) } } +wxCoord wxComboListBox::GetBestWidth() const +{ + wxSize size = wxListBox::GetBestSize(); + return size.x; +} + wxSize wxComboListBox::DoGetBestClientSize() const { // don't return size too big or we risk to not fit on the screen @@ -705,10 +764,16 @@ void wxComboBox::SetEditable(bool editable) void wxComboBox::Clear() { GetLBox()->Clear(); + GetText()->SetValue(wxEmptyString); } void wxComboBox::Delete(int n) { + wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxComboBox::Delete") ); + + if (GetSelection() == n) + GetText()->SetValue(wxEmptyString); + GetLBox()->Delete(n); } @@ -719,11 +784,15 @@ int wxComboBox::GetCount() const wxString wxComboBox::GetString(int n) const { + wxCHECK_MSG( (n >= 0) && (n < GetCount()), wxEmptyString, _T("invalid index in wxComboBox::GetString") ); + return GetLBox()->GetString(n); } void wxComboBox::SetString(int n, const wxString& s) { + wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxComboBox::SetString") ); + GetLBox()->SetString(n, s); } @@ -734,7 +803,7 @@ int wxComboBox::FindString(const wxString& s) const void wxComboBox::Select(int n) { - wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid combobox index") ); + wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxComboBox::Select") ); GetLBox()->SetSelection(n); GetText()->SetValue(GetLBox()->GetString(n)); @@ -742,8 +811,15 @@ void wxComboBox::Select(int n) int wxComboBox::GetSelection() const { +#if 1 // FIXME:: What is the correct behavior? // if the current value isn't one of the listbox strings, return -1 + return GetLBox()->GetSelection(); +#else + // Why oh why is this done this way? + // It is not because the value displayed in the text can be found + // in the list that it is the item that is selected! return FindString(GetText()->GetValue()); +#endif } int wxComboBox::DoAppend(const wxString& item) @@ -751,6 +827,18 @@ int wxComboBox::DoAppend(const wxString& item) return GetLBox()->Append(item); } +int wxComboBox::DoInsert(const wxString& item, int pos) +{ + wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list")); + wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index")); + + if (pos == GetCount()) + return DoAppend(item); + + GetLBox()->Insert(item, pos); + return pos; +} + void wxComboBox::DoSetItemClientData(int n, void* clientData) { GetLBox()->SetClientData(n, clientData); @@ -775,7 +863,7 @@ wxClientData* wxComboBox::DoGetItemClientObject(int n) const // input handling // ---------------------------------------------------------------------------- -void wxComboControl::OnKey(wxCommandEvent& event) +void wxComboControl::OnKey(wxKeyEvent& event) { if ( m_isPopupShown ) {