X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a57d600f1aa4bae88f4c9b8d89a35332c412939e..f5bed7a885024108682c32c74567cdf7bf2ed13b:/src/common/combocmn.cpp diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index bf2e830a65..e2a0fd70c3 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: combocmn.cpp +// Name: src/common/combocmn.cpp // Purpose: wxComboCtrlBase // Author: Jaakko Salli // Modified by: @@ -25,18 +25,18 @@ #if wxUSE_COMBOCTRL +#include "wx/combobox.h" + #ifndef WX_PRECOMP - #include "wx/defs.h" #include "wx/log.h" - #include "wx/combobox.h" #include "wx/dcclient.h" #include "wx/settings.h" #include "wx/dialog.h" + #include "wx/timer.h" #endif #include "wx/dcbuffer.h" #include "wx/tooltip.h" -#include "wx/timer.h" #include "wx/combo.h" @@ -694,13 +694,13 @@ void wxComboCtrlBase::Init() } bool wxComboCtrlBase::Create(wxWindow *parent, - wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator& validator, - const wxString& name) + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) { if ( !wxControl::Create(parent, id, @@ -717,6 +717,16 @@ bool wxComboCtrlBase::Create(wxWindow *parent, OnThemeChange(); m_absIndent = GetNativeTextIndent(); + m_iFlags |= wxCC_IFLAG_CREATED; + + // If x and y indicate valid size, wxSizeEvent won't be + // emitted automatically, so we need to add artifical one. + if ( size.x > 0 && size.y > 0 ) + { + wxSizeEvent evt(size,GetId()); + GetEventHandler()->AddPendingEvent(evt); + } + return true; } @@ -733,24 +743,23 @@ void wxComboCtrlBase::InstallInputHandlers( bool alsoTextCtrl ) m_extraEvtHandler = inputHandler; } -void wxComboCtrlBase::CreateTextCtrl( int extraStyle, const wxValidator& validator ) +void +wxComboCtrlBase::CreateTextCtrl(int style, const wxValidator& validator) { if ( !(m_windowStyle & wxCB_READONLY) ) { - m_text = new wxTextCtrl(this, - 12345, - m_valueString, - wxDefaultPosition, - wxDefaultSize, - // wxTE_PROCESS_TAB is needed because on Windows, wxTAB_TRAVERSAL is - // not used by the wxPropertyGrid and therefore the tab is - // processed by looking at ancestors to see if they have - // wxTAB_TRAVERSAL. The navigation event is then sent to - // the wrong window. - wxTE_PROCESS_TAB | - wxTE_PROCESS_ENTER | - extraStyle, - validator); + // wxTE_PROCESS_TAB is needed because on Windows, wxTAB_TRAVERSAL is + // not used by the wxPropertyGrid and therefore the tab is processed by + // looking at ancestors to see if they have wxTAB_TRAVERSAL. The + // navigation event is then sent to the wrong window. + style |= wxTE_PROCESS_TAB; + + if ( HasFlag(wxTE_PROCESS_ENTER) ) + style |= wxTE_PROCESS_ENTER; + + m_text = new wxTextCtrl(this, wxID_ANY, m_valueString, + wxDefaultPosition, wxDefaultSize, + style, validator); // This is required for some platforms (GTK+ atleast) m_text->SetSizeHints(2,4); @@ -775,15 +784,7 @@ wxComboCtrlBase::~wxComboCtrlBase() m_toplevEvtHandler = (wxEvtHandler*) NULL; #endif - if ( m_popup ) - m_popup->RemoveEventHandler(m_popupExtraHandler); - - delete m_popupExtraHandler; - - HidePopup(); - - delete m_popupInterface; - delete m_winPopup; + DestroyPopup(); RemoveEventHandler(m_extraEvtHandler); @@ -804,7 +805,6 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth ) { wxSize sz = GetClientSize(); int customBorder = m_widthCustomBorder; - bool buttonOutside; int btnBorder; // border for button only // check if button should really be outside the border: we'll do it it if @@ -815,13 +815,11 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth ) m_btnSpacingX == 0 && m_btnHei == 0 ) { - buttonOutside = true; m_iFlags |= wxCC_IFLAG_BUTTON_OUTSIDE; btnBorder = 0; } else { - buttonOutside = false; m_iFlags &= ~(wxCC_IFLAG_BUTTON_OUTSIDE); btnBorder = customBorder; } @@ -840,15 +838,31 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth ) if ( butWidth <= 0 ) return; + int butHeight = sz.y - btnBorder*2; + // Adjust button width if ( m_btnWid < 0 ) butWidth += m_btnWid; else if ( m_btnWid > 0 ) butWidth = m_btnWid; + else + { + // Adjust button width to match aspect ratio + // (but only if control is smaller than best size). + int bestHeight = GetBestSize().y; + int height = GetSize().y; - int butHeight = sz.y; - - butHeight -= btnBorder*2; + if ( height < bestHeight ) + { + // Make very small buttons square, as it makes + // them accommodate arrow image better and still + // looks decent. + if ( height > 18 ) + butWidth = (height*butWidth)/bestHeight; + else + butWidth = butHeight; + } + } // Adjust button height if ( m_btnHei < 0 ) @@ -881,7 +895,7 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth ) if ( (sz.y-(customBorder*2)) < butHeight && btnWidth == 0 ) { int newY = butHeight+(customBorder*2); - SetClientSize(-1,newY); + SetClientSize(wxDefaultCoord,newY); sz.y = newY; } } @@ -999,14 +1013,6 @@ wxSize wxComboCtrlBase::DoGetBestSize() const return ret; } -void wxComboCtrlBase::DoMoveWindow(int x, int y, int width, int height) -{ - // SetSize is called last in create, so it marks the end of creation - m_iFlags |= wxCC_IFLAG_CREATED; - - wxControl::DoMoveWindow(x, y, width, height); -} - void wxComboCtrlBase::OnSizeEvent( wxSizeEvent& event ) { if ( !IsCreated() ) @@ -1085,7 +1091,7 @@ void wxComboCtrlBase::DoSetToolTip(wxToolTip *tooltip) // ---------------------------------------------------------------------------- // draw focus background on area in a way typical on platform -void wxComboCtrlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) +void wxComboCtrlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) const { wxSize sz = GetClientSize(); bool isEnabled; @@ -1119,8 +1125,14 @@ void wxComboCtrlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int fla wxRect selRect(rect); selRect.y += focusSpacingY; selRect.height -= (focusSpacingY*2); - selRect.x += m_widthCustomPaint + focusSpacingX; - selRect.width -= m_widthCustomPaint + (focusSpacingX*2); + + int wcp = 0; + + if ( !(flags & wxCONTROL_ISSUBMENU) ) + wcp += m_widthCustomPaint; + + selRect.x += wcp + focusSpacingX; + selRect.width -= wcp + (focusSpacingX*2); wxColour bgCol; @@ -1178,9 +1190,19 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, bool paintBg ) if ( !m_bmpNormal.Ok() ) { // Need to clear button background even if m_btn is present - // (assume non-button background was cleared just before this call so brushes are good) if ( paintBg ) + { + wxColour bgCol; + + if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE ) + bgCol = GetParent()->GetBackgroundColour(); + else + bgCol = GetBackgroundColour(); + + dc.SetBrush(bgCol); + dc.SetPen(bgCol); dc.DrawRectangle(rect); + } // Draw standard button wxRendererNative::Get().DrawComboBoxDropButton(this, @@ -1268,8 +1290,11 @@ wxBitmap& wxComboCtrlBase::GetBufferBitmap( const wxSize& sz ) const void wxComboCtrlBase::OnTextCtrlEvent(wxCommandEvent& event) { - // Change event id and relay it forward + // Change event id, object and string before relaying it forward event.SetId(GetId()); + wxString s = event.GetString(); + event.SetEventObject(this); + event.SetString(s); event.Skip(); } @@ -1522,19 +1547,39 @@ void wxComboCtrlBase::CreatePopup() popupInterface->m_iFlags |= wxCP_IFLAG_CREATED; } -void wxComboCtrlBase::SetPopupControl( wxComboPopup* iface ) +// Destroy popup window and the child control +void wxComboCtrlBase::DestroyPopup() { - wxCHECK_RET( iface, wxT("no popup interface set for wxComboCtrl") ); + if ( m_popup ) + m_popup->RemoveEventHandler(m_popupExtraHandler); + + delete m_popupExtraHandler; + + HidePopup(); delete m_popupInterface; - delete m_winPopup; + + if ( m_winPopup ) + m_winPopup->Destroy(); + + m_popupExtraHandler = (wxEvtHandler*) NULL; + m_popupInterface = (wxComboPopup*) NULL; + m_winPopup = (wxWindow*) NULL; + m_popup = (wxWindow*) NULL; +} + +void wxComboCtrlBase::DoSetPopupControl(wxComboPopup* iface) +{ + wxCHECK_RET( iface, wxT("no popup interface set for wxComboCtrl") ); + + DestroyPopup(); iface->InitBase(this); iface->Init(); m_popupInterface = iface; - if ( !iface->LazyCreate() || m_winPopup ) + if ( !iface->LazyCreate() ) { CreatePopup(); } @@ -1644,15 +1689,45 @@ void wxComboCtrlBase::ShowPopup() int popupX; int popupY = scrPos.y + ctrlSz.y; + // Default anchor is wxLEFT int anchorSide = m_anchorSide; if ( !anchorSide ) - anchorSide = m_btnSide; + anchorSide = wxLEFT; + + int rightX = scrPos.x + ctrlSz.x + m_extRight - szp.x; + int leftX = scrPos.x - m_extLeft; + int screenWidth = wxSystemSettings::GetMetric( wxSYS_SCREEN_X ); + + // If there is not enough horizontal space, anchor on the other side. + // If there is no space even then, place the popup at x 0. + if ( anchorSide == wxRIGHT ) + { + if ( rightX < 0 ) + { + if ( (leftX+szp.x) < screenWidth ) + anchorSide = wxLEFT; + else + anchorSide = 0; + } + } + else + { + if ( (leftX+szp.x) >= screenWidth ) + { + if ( rightX >= 0 ) + anchorSide = wxRIGHT; + else + anchorSide = 0; + } + } - // Anchor popup to the side the dropbutton is on + // Select x coordinate according to the anchor side if ( anchorSide == wxRIGHT ) - popupX = scrPos.x + ctrlSz.x + m_extRight- szp.x; + popupX = rightX; + else if ( anchorSide == wxLEFT ) + popupX = leftX; else - popupX = scrPos.x - m_extLeft; + popupX = 0; if ( spaceBelow < szp.y ) {