X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/118f5fbd0651e6c610a44a42a41dcf93439e820d..187d815255d240350c598721db1e0c1b4d3fb527:/src/common/combocmn.cpp diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index 0157152551..0b53234ca9 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -35,7 +35,6 @@ #include "wx/timer.h" #endif -#include "wx/dcbuffer.h" #include "wx/tooltip.h" #include "wx/combo.h" @@ -53,7 +52,7 @@ #define BMP_BUTTON_MARGIN 4 -#define DEFAULT_POPUP_HEIGHT 200 +#define DEFAULT_POPUP_HEIGHT 400 #define DEFAULT_TEXT_INDENT 3 @@ -63,21 +62,43 @@ #if defined(__WXMSW__) #define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) +#define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common + // native controls work on it like normal. +#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window. +#define TEXTCTRL_TEXT_CENTERED 0 // 1 if text in textctrl is vertically centered //#undef wxUSE_POPUPWIN //#define wxUSE_POPUPWIN 0 #elif defined(__WXGTK__) +// NB: It is not recommended to use wxDialog as popup on wxGTK, because of +// this bug: If wxDialog is hidden, its position becomes corrupt +// between hide and next show, but without internal coordinates being +// reflected (or something like that - atleast commenting out ->Hide() +// seemed to eliminate the position change). + #define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) +#define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common + // native controls work on it like normal. +#define POPUPWIN_IS_PERFECT 1 // Same, but for non-transient popup window. +#define TEXTCTRL_TEXT_CENTERED 1 // 1 if text in textctrl is vertically centered #elif defined(__WXMAC__) #define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform) +#define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common + // native controls work on it like normal. +#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window. +#define TEXTCTRL_TEXT_CENTERED 1 // 1 if text in textctrl is vertically centered #else #define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform) +#define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common + // native controls work on it like normal. +#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window. +#define TEXTCTRL_TEXT_CENTERED 1 // 1 if text in textctrl is vertically centered #endif @@ -99,23 +120,76 @@ #endif -#if USE_TRANSIENT_POPUP +// Define different types of popup windows +enum +{ + POPUPWIN_NONE = 0, + POPUPWIN_WXPOPUPTRANSIENTWINDOW = 1, + POPUPWIN_WXPOPUPWINDOW = 2, + POPUPWIN_WXDIALOG = 3 +}; - #define wxComboPopupWindowBase wxPopupTransientWindow - #define INSTALL_TOPLEV_HANDLER 0 + +#if USE_TRANSIENT_POPUP + // wxPopupTransientWindow is implemented + + #define wxComboPopupWindowBase wxPopupTransientWindow + #define PRIMARY_POPUP_TYPE POPUPWIN_WXPOPUPTRANSIENTWINDOW + #define USES_WXPOPUPTRANSIENTWINDOW 1 + + #if TRANSIENT_POPUPWIN_IS_PERFECT + // + #elif POPUPWIN_IS_PERFECT + #define wxComboPopupWindowBase2 wxPopupWindow + #define SECONDARY_POPUP_TYPE POPUPWIN_WXPOPUPWINDOW + #define USES_WXPOPUPWINDOW 1 + #else + #define wxComboPopupWindowBase2 wxDialog + #define SECONDARY_POPUP_TYPE POPUPWIN_WXDIALOG + #define USES_WXDIALOG 1 + #endif #elif wxUSE_POPUPWIN + // wxPopupWindow (but not wxPopupTransientWindow) is properly implemented + + #define wxComboPopupWindowBase wxPopupWindow + #define PRIMARY_POPUP_TYPE POPUPWIN_WXPOPUPWINDOW + #define USES_WXPOPUPWINDOW 1 - #define wxComboPopupWindowBase wxPopupWindow - #define INSTALL_TOPLEV_HANDLER 1 + #if !POPUPWIN_IS_PERFECT + #define wxComboPopupWindowBase2 wxDialog + #define SECONDARY_POPUP_TYPE POPUPWIN_WXDIALOG + #define USES_WXDIALOG 1 + #endif #else + // wxPopupWindow is not implemented + + #define wxComboPopupWindowBase wxDialog + #define PRIMARY_POPUP_TYPE POPUPWIN_WXDIALOG + #define USES_WXDIALOG 1 + +#endif + - #define wxComboPopupWindowBase wxDialog - #define INSTALL_TOPLEV_HANDLER 0 // Doesn't need since can monitor active event +#ifndef USES_WXPOPUPTRANSIENTWINDOW + #define USES_WXPOPUPTRANSIENTWINDOW 0 +#endif +#ifndef USES_WXPOPUPWINDOW + #define USES_WXPOPUPWINDOW 0 #endif +#ifndef USES_WXDIALOG + #define USES_WXDIALOG 0 +#endif + + +#if USES_WXPOPUPWINDOW + #define INSTALL_TOPLEV_HANDLER 1 +#else + #define INSTALL_TOPLEV_HANDLER 0 +#endif // @@ -140,7 +214,7 @@ class wxComboFrameEventHandler : public wxEvtHandler { public: wxComboFrameEventHandler( wxComboCtrlBase* pCb ); - ~wxComboFrameEventHandler(); + virtual ~wxComboFrameEventHandler(); void OnPopup(); @@ -249,7 +323,7 @@ void wxComboFrameEventHandler::OnMove( wxMoveEvent& event ) #endif // INSTALL_TOPLEV_HANDLER // ---------------------------------------------------------------------------- -// wxComboPopupWindow is wxPopupWindow customized for +// wxComboPopupWindow is, in essence, wxPopupWindow customized for // wxComboCtrl. // ---------------------------------------------------------------------------- @@ -257,105 +331,105 @@ class wxComboPopupWindow : public wxComboPopupWindowBase { public: - wxComboPopupWindow( wxComboCtrlBase *parent, int style = wxBORDER_NONE ); + wxComboPopupWindow( wxComboCtrlBase *parent, + int style ) + #if USES_WXPOPUPWINDOW || USES_WXPOPUPTRANSIENTWINDOW + : wxComboPopupWindowBase(parent,style) + #else + : wxComboPopupWindowBase(parent, + wxID_ANY, + wxEmptyString, + wxPoint(-21,-21), + wxSize(20,20), + style) + #endif + { + } -#if USE_TRANSIENT_POPUP +#if USES_WXPOPUPTRANSIENTWINDOW virtual bool ProcessLeftDown(wxMouseEvent& event); + virtual void OnDismiss(); #endif - void OnKeyEvent(wxKeyEvent& event); +}; - void OnMouseEvent( wxMouseEvent& event ); -#if !wxUSE_POPUPWIN - void OnActivate( wxActivateEvent& event ); -#endif -protected: +#if USES_WXPOPUPTRANSIENTWINDOW +bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event ) +{ + return wxComboPopupWindowBase::ProcessLeftDown(event); +} -#if USE_TRANSIENT_POPUP - virtual void OnDismiss(); +// First thing that happens when a transient popup closes is that this method gets called. +void wxComboPopupWindow::OnDismiss() +{ + wxComboCtrlBase* combo = (wxComboCtrlBase*) GetParent(); + wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxComboCtrlBase)), + wxT("parent might not be wxComboCtrl, but check IMPLEMENT_DYNAMIC_CLASS(2) macro for correctness") ); + + combo->OnPopupDismiss(); +} +#endif // USES_WXPOPUPTRANSIENTWINDOW + + +// ---------------------------------------------------------------------------- +// wxComboPopupWindowEvtHandler does bulk of the custom event handling +// of a popup window. It is separate so we can have different types +// of popup windows. +// ---------------------------------------------------------------------------- + +class wxComboPopupWindowEvtHandler : public wxEvtHandler +{ +public: + + wxComboPopupWindowEvtHandler( wxComboCtrlBase *parent ) + { + m_combo = parent; + } + + void OnKeyEvent(wxKeyEvent& event); +#if USES_WXDIALOG + void OnActivate( wxActivateEvent& event ); #endif private: + wxComboCtrlBase* m_combo; + DECLARE_EVENT_TABLE() }; -BEGIN_EVENT_TABLE(wxComboPopupWindow, wxComboPopupWindowBase) - EVT_MOUSE_EVENTS(wxComboPopupWindow::OnMouseEvent) -#if !wxUSE_POPUPWIN - EVT_ACTIVATE(wxComboPopupWindow::OnActivate) +BEGIN_EVENT_TABLE(wxComboPopupWindowEvtHandler, wxEvtHandler) + EVT_KEY_DOWN(wxComboPopupWindowEvtHandler::OnKeyEvent) + EVT_KEY_UP(wxComboPopupWindowEvtHandler::OnKeyEvent) +#if USES_WXDIALOG + EVT_ACTIVATE(wxComboPopupWindowEvtHandler::OnActivate) #endif - EVT_KEY_DOWN(wxComboPopupWindow::OnKeyEvent) - EVT_KEY_UP(wxComboPopupWindow::OnKeyEvent) END_EVENT_TABLE() -wxComboPopupWindow::wxComboPopupWindow( wxComboCtrlBase *parent, - int style ) -#if wxUSE_POPUPWIN - : wxComboPopupWindowBase(parent,style) -#else - : wxComboPopupWindowBase(parent, - wxID_ANY, - wxEmptyString, - wxPoint(-21,-21), - wxSize(20,20), - style) -#endif -{ -} - -void wxComboPopupWindow::OnKeyEvent( wxKeyEvent& event ) +void wxComboPopupWindowEvtHandler::OnKeyEvent( wxKeyEvent& event ) { // Relay keyboard event to the main child controls - // (just skipping may just cause the popup to close) - wxWindowList children = GetChildren(); + wxWindowList children = m_combo->GetPopupWindow()->GetChildren(); wxWindowList::iterator node = children.begin(); wxWindow* child = (wxWindow*)*node; child->AddPendingEvent(event); } -void wxComboPopupWindow::OnMouseEvent( wxMouseEvent& event ) -{ - event.Skip(); -} - -#if !wxUSE_POPUPWIN -void wxComboPopupWindow::OnActivate( wxActivateEvent& event ) +#if USES_WXDIALOG +void wxComboPopupWindowEvtHandler::OnActivate( wxActivateEvent& event ) { if ( !event.GetActive() ) { // Tell combo control that we are dismissed. - wxComboCtrl* combo = (wxComboCtrl*) GetParent(); - wxASSERT( combo ); - wxASSERT( combo->IsKindOf(CLASSINFO(wxComboCtrl)) ); - - combo->HidePopup(); + m_combo->HidePopup(); event.Skip(); } } #endif -#if USE_TRANSIENT_POPUP -bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event ) -{ - return wxComboPopupWindowBase::ProcessLeftDown(event); -} -#endif - -#if USE_TRANSIENT_POPUP -// First thing that happens when a transient popup closes is that this method gets called. -void wxComboPopupWindow::OnDismiss() -{ - wxComboCtrlBase* combo = (wxComboCtrlBase*) GetParent(); - wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxComboCtrlBase)), - wxT("parent might not be wxComboCtrl, but check IMPLEMENT_DYNAMIC_CLASS(2) macro for correctness") ); - - combo->OnPopupDismiss(); -} -#endif // ---------------------------------------------------------------------------- // wxComboPopup @@ -438,7 +512,7 @@ public: { m_combo = combo; } - ~wxComboBoxExtraInputHandler() { } + virtual ~wxComboBoxExtraInputHandler() { } void OnKey(wxKeyEvent& event); void OnFocus(wxFocusEvent& event); @@ -510,7 +584,7 @@ public: m_combo = combo; m_beenInside = false; } - ~wxComboPopupExtraEventHandler() { } + virtual ~wxComboPopupExtraEventHandler() { } void OnMouseEvent( wxMouseEvent& event ); @@ -610,9 +684,6 @@ END_EVENT_TABLE() IMPLEMENT_ABSTRACT_CLASS(wxComboCtrlBase, wxControl) -// Have global double buffer - should be enough for multiple combos -static wxBitmap* gs_doubleBuffer = (wxBitmap*) NULL; - void wxComboCtrlBase::Init() { m_winPopup = (wxWindow *)NULL; @@ -638,6 +709,8 @@ void wxComboCtrlBase::Init() m_btnState = 0; m_btnWidDefault = 0; m_blankButtonBg = false; + m_ignoreEvtText = 0; + m_popupWinType = POPUPWIN_NONE; m_btnWid = m_btnHei = -1; m_btnSide = wxRIGHT; m_btnSpacingX = 0; @@ -646,7 +719,6 @@ void wxComboCtrlBase::Init() m_extRight = 0; m_absIndent = -1; m_iFlags = 0; - m_downReceived = false; m_timeCanAcceptClick = 0; } @@ -701,6 +773,9 @@ wxComboCtrlBase::CreateTextCtrl(int style, const wxValidator& validator) { if ( !(m_windowStyle & wxCB_READONLY) ) { + if ( m_text ) + m_text->Destroy(); + // 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 @@ -710,6 +785,14 @@ wxComboCtrlBase::CreateTextCtrl(int style, const wxValidator& validator) if ( HasFlag(wxTE_PROCESS_ENTER) ) style |= wxTE_PROCESS_ENTER; + // Ignore EVT_TEXT generated by the constructor (but only + // if the event redirector already exists) + // NB: This must be " = 1" instead of "++"; + if ( m_textEvtHandler ) + m_ignoreEvtText = 1; + else + m_ignoreEvtText = 0; + m_text = new wxTextCtrl(this, wxID_ANY, m_valueString, wxDefaultPosition, wxDefaultSize, style, validator); @@ -729,9 +812,6 @@ wxComboCtrlBase::~wxComboCtrlBase() if ( HasCapture() ) ReleaseMouse(); - delete gs_doubleBuffer; - gs_doubleBuffer = (wxBitmap*) NULL; - #if INSTALL_TOPLEV_HANDLER delete ((wxComboFrameEventHandler*)m_toplevEvtHandler); m_toplevEvtHandler = (wxEvtHandler*) NULL; @@ -878,6 +958,7 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust wxSize sz = GetClientSize(); int customBorder = m_widthCustomBorder; +#if !TEXTCTRL_TEXT_CENTERED if ( (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER ) { // Centre textctrl @@ -904,11 +985,16 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust } } else +#else + wxUnusedVar(textCtrlXAdjust); + wxUnusedVar(textCtrlYAdjust); +#endif { - m_text->SetSize( m_tcArea.x, - 0, - sz.x - m_btnArea.x - m_widthCustomPaint - customBorder, - sz.y ); + // If it has border, have textctrl will the entire text field. + m_text->SetSize( m_tcArea.x + m_widthCustomPaint, + customBorder, + sz.x - m_btnArea.width - m_widthCustomPaint - customBorder, + sz.y-(customBorder*2) ); } } @@ -1230,25 +1316,21 @@ void wxComboCtrlBase::RecalcAndRefresh() } } -wxBitmap& wxComboCtrlBase::GetBufferBitmap( const wxSize& sz ) const -{ - // If size is larger, recalculate double buffer bitmap - if ( !gs_doubleBuffer || - sz.x > gs_doubleBuffer->GetWidth() || - sz.y > gs_doubleBuffer->GetHeight() ) - { - delete gs_doubleBuffer; - gs_doubleBuffer = new wxBitmap(sz.x+25,sz.y); - } - return *gs_doubleBuffer; -} - // ---------------------------------------------------------------------------- // miscellaneous event handlers // ---------------------------------------------------------------------------- void wxComboCtrlBase::OnTextCtrlEvent(wxCommandEvent& event) { + if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED ) + { + if ( m_ignoreEvtText > 0 ) + { + m_ignoreEvtText--; + return; + } + } + // Change event id, object and string before relaying it forward event.SetId(GetId()); wxString s = event.GetString(); @@ -1285,26 +1367,17 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event, } else if ( type == wxEVT_LEFT_DOWN ) { - // Only accept event if it wasn't right after popup dismiss - //if ( ::wxGetLocalTimeMillis() > m_timeCanClick ) + if ( flags & (wxCC_MF_ON_CLICK_AREA|wxCC_MF_ON_BUTTON) ) { - // Need to test this, because it might be outside. - if ( flags & wxCC_MF_ON_BUTTON ) - { - m_btnState |= wxCONTROL_PRESSED; - Refresh(); + m_btnState |= wxCONTROL_PRESSED; + Refresh(); - if ( !(m_iFlags & wxCC_POPUP_ON_MOUSE_UP) ) - OnButtonClick(); - else - // If showing popup now, do not capture mouse or there will be interference - CaptureMouse(); - } + if ( !(m_iFlags & wxCC_POPUP_ON_MOUSE_UP) ) + OnButtonClick(); + else + // If showing popup now, do not capture mouse or there will be interference + CaptureMouse(); } - /*else - { - m_btnState = 0; - }*/ } else if ( type == wxEVT_LEFT_UP ) { @@ -1318,7 +1391,7 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event, // If mouse was inside, fire the click event. if ( m_iFlags & wxCC_POPUP_ON_MOUSE_UP ) { - if ( flags & wxCC_MF_ON_BUTTON ) + if ( flags & (wxCC_MF_ON_CLICK_AREA|wxCC_MF_ON_BUTTON) ) OnButtonClick(); } @@ -1346,65 +1419,24 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event, return true; } -// Conversion to double-clicks and some basic filtering // returns true if event was consumed or filtered -//bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event, bool isOnButtonArea ) bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event, - int flags ) + int WXUNUSED(flags) ) { wxLongLong t = ::wxGetLocalTimeMillis(); int evtType = event.GetEventType(); -#if !USE_TRANSIENT_POPUP - if ( m_isPopupShown && - ( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) ) +#if USES_WXPOPUPWINDOW || USES_WXDIALOG + if ( m_popupWinType != POPUPWIN_WXPOPUPTRANSIENTWINDOW ) { - HidePopup(); - return true; - } -#endif - - // - // Generate our own double-clicks - // (to allow on-focus dc-event on double-clicks instead of triple-clicks) - if ( (m_windowStyle & wxCC_SPECIAL_DCLICK) && - !m_isPopupShown && - //!(handlerFlags & wxCC_MF_ON_BUTTON) ) - !(flags & wxCC_MF_ON_BUTTON) ) - { - if ( evtType == wxEVT_LEFT_DOWN ) - { - // Set value to avoid up-events without corresponding downs - m_downReceived = true; - } - else if ( evtType == wxEVT_LEFT_DCLICK ) + if ( m_isPopupShown && + ( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) ) { - // We'll make our own double-clicks - //evtType = 0; - event.SetEventType(0); + HidePopup(); return true; } - else if ( evtType == wxEVT_LEFT_UP ) - { - if ( m_downReceived || m_timeLastMouseUp == 1 ) - { - wxLongLong timeFromLastUp = (t-m_timeLastMouseUp); - - if ( timeFromLastUp < DOUBLE_CLICK_CONVERSION_TRESHOLD ) - { - //type = wxEVT_LEFT_DCLICK; - event.SetEventType(wxEVT_LEFT_DCLICK); - m_timeLastMouseUp = 1; - } - else - { - m_timeLastMouseUp = t; - } - - //m_downReceived = false; - } - } } +#endif // Filter out clicks on button immediately after popup dismiss (Windows like behaviour) if ( evtType == wxEVT_LEFT_DOWN && t < m_timeCanAcceptClick ) @@ -1425,11 +1457,10 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event ) { if ( m_isPopupShown ) { - #if !wxUSE_POPUPWIN - // Normally do nothing - evt handler should close it for us - #elif !USE_TRANSIENT_POPUP + #if USES_WXPOPUPWINDOW // Click here always hides the popup. - HidePopup(); + if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW ) + HidePopup(); #endif } else @@ -1511,12 +1542,6 @@ void wxComboCtrlBase::OnFocusEvent( wxFocusEvent& event ) { if ( event.GetEventType() == wxEVT_SET_FOCUS ) { - // First click is the first part of double-click - // Some platforms don't generate down-less mouse up-event - // (Windows does, GTK+2 doesn't), so that's why we have - // to do this. - m_timeLastMouseUp = ::wxGetLocalTimeMillis(); - if ( m_text && m_text != ::wxWindow::FindFocus() ) m_text->SetFocus(); } @@ -1544,7 +1569,28 @@ void wxComboCtrlBase::CreatePopup() wxWindow* popup; if ( !m_winPopup ) - m_winPopup = new wxComboPopupWindow( this, wxNO_BORDER ); + { +#ifdef wxComboPopupWindowBase2 + if ( m_iFlags & wxCC_IFLAG_USE_ALT_POPUP ) + { + #if !USES_WXDIALOG + m_winPopup = new wxComboPopupWindowBase2( this, wxNO_BORDER ); + #else + m_winPopup = new wxComboPopupWindowBase2( this, wxID_ANY, wxEmptyString, + wxPoint(-21,-21), wxSize(20, 20), + wxNO_BORDER ); + #endif + m_popupWinType = SECONDARY_POPUP_TYPE; + } + else +#endif + { + m_winPopup = new wxComboPopupWindow( this, wxNO_BORDER ); + m_popupWinType = PRIMARY_POPUP_TYPE; + } + m_popupWinEvtHandler = new wxComboPopupWindowEvtHandler(this); + m_winPopup->PushEventHandler(m_popupWinEvtHandler); + } popupInterface->Create(m_winPopup); m_popup = popup = popupInterface->GetControl(); @@ -1573,7 +1619,12 @@ void wxComboCtrlBase::DestroyPopup() delete m_popupInterface; if ( m_winPopup ) + { + m_winPopup->RemoveEventHandler(m_popupWinEvtHandler); + delete m_popupWinEvtHandler; + m_popupWinEvtHandler = NULL; m_winPopup->Destroy(); + } m_popupExtraHandler = (wxEvtHandler*) NULL; m_popupInterface = (wxComboPopup*) NULL; @@ -1777,32 +1828,47 @@ void wxComboCtrlBase::ShowPopup() m_isPopupShown = true; // Show it -#if USE_TRANSIENT_POPUP - ((wxPopupTransientWindow*)winPopup)->Popup(popup); -#else - winPopup->Show(); +#if USES_WXPOPUPTRANSIENTWINDOW + if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW ) + ((wxPopupTransientWindow*)winPopup)->Popup(popup); + else #endif + winPopup->Show(); #if INSTALL_TOPLEV_HANDLER // Put top level window event handler into place - if ( !m_toplevEvtHandler ) - m_toplevEvtHandler = new wxComboFrameEventHandler(this); + if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW ) + { + if ( !m_toplevEvtHandler ) + m_toplevEvtHandler = new wxComboFrameEventHandler(this); - wxWindow* toplev = ::wxGetTopLevelParent( this ); - wxASSERT( toplev ); - ((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup(); - toplev->PushEventHandler( m_toplevEvtHandler ); + wxWindow* toplev = ::wxGetTopLevelParent( this ); + wxASSERT( toplev ); + ((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup(); + toplev->PushEventHandler( m_toplevEvtHandler ); + } #endif } void wxComboCtrlBase::OnPopupDismiss() -{ +{ // Just in case, avoid double dismiss if ( !m_isPopupShown ) return; - // *Must* set this before focus etc. + // NB: Focus setting is really funny, atleast on wxMSW. First of all, + // we need to have SetFocus at the end. Otherwise wxTextCtrl may + // freeze until focus goes somewhere else. Second, wxTreeCtrl as + // popup, when dismissing, "steals" focus back to itself unless + // SetFocus is called also here, exactly before m_isPopupShown + // is set to false. Which is truly weird since SetFocus is just + // wxWindowMSW method and does not call event handler or anything like + // that (ie. does not care about m_isPopupShown). + + SetFocus(); + + // This should preferably be set before focus. m_isPopupShown = false; // Inform popup control itself @@ -1825,7 +1891,7 @@ void wxComboCtrlBase::OnPopupDismiss() // If cursor not on dropdown button, then clear its state // (technically not required by all ports, but do it for all just in case) - if ( !m_btnArea.Inside(ScreenToClient(::wxGetMousePosition())) ) + if ( !m_btnArea.Contains(ScreenToClient(::wxGetMousePosition())) ) m_btnState = 0; // Return parent's tab traversal flag. @@ -1840,10 +1906,7 @@ void wxComboCtrlBase::OnPopupDismiss() // refresh control (necessary even if m_text) Refresh(); -#if !wxUSE_POPUPWIN SetFocus(); -#endif - } void wxComboCtrlBase::HidePopup() @@ -1856,11 +1919,12 @@ void wxComboCtrlBase::HidePopup() // transfer value and show it in textctrl, if any SetValue( m_popupInterface->GetStringValue() ); -#if USE_TRANSIENT_POPUP - ((wxPopupTransientWindow*)m_winPopup)->Dismiss(); -#else - m_winPopup->Hide(); +#if USES_WXPOPUPTRANSIENTWINDOW + if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW ) + ((wxPopupTransientWindow*)m_winPopup)->Dismiss(); + else #endif + m_winPopup->Hide(); OnPopupDismiss(); } @@ -1975,10 +2039,13 @@ wxString wxComboCtrlBase::GetValue() const return m_valueString; } -void wxComboCtrlBase::SetValue(const wxString& value) +void wxComboCtrlBase::SetValueWithEvent(const wxString& value, bool withEvent) { if ( m_text ) { + if ( !withEvent ) + m_ignoreEvtText++; + m_text->SetValue(value); if ( !(m_iFlags & wxCC_NO_TEXT_AUTO_SELECT) ) m_text->SelectAll(); @@ -1996,6 +2063,11 @@ void wxComboCtrlBase::SetValue(const wxString& value) } } +void wxComboCtrlBase::SetValue(const wxString& value) +{ + SetValueWithEvent(value, false); +} + // In this SetValue variant wxComboPopup::SetStringValue is not called void wxComboCtrlBase::SetText(const wxString& value) { @@ -2005,6 +2077,12 @@ void wxComboCtrlBase::SetText(const wxString& value) m_valueString = value; + if ( m_text ) + { + m_ignoreEvtText++; + m_text->SetValue( value ); + } + Refresh(); }