Replace wxComboPopupEvtHandler with calls to Bind() as well

This is not as much of a simplification as the previous two commits
because there is no simple replacement of EVT_MOUSE_EVENTS() using
Bind() and a loop over all mouse event types has to be written
explicitly, but it still avoids the need to allocate and delete a
separate object, so is still worth it.
This commit is contained in:
Vadim Zeitlin
2021-07-10 19:33:01 +01:00
parent f3fb6dc833
commit d7d5231e96
2 changed files with 55 additions and 69 deletions

View File

@@ -579,6 +579,8 @@ protected:
void OnPopupKey(wxKeyEvent& event); void OnPopupKey(wxKeyEvent& event);
void OnPopupSize(wxSizeEvent& event); void OnPopupSize(wxSizeEvent& event);
void OnPopupMouseEvent(wxMouseEvent& event);
// Set customization flags (directs how wxComboCtrlBase helpers behave) // Set customization flags (directs how wxComboCtrlBase helpers behave)
void Customize( wxUint32 flags ) { m_iFlags |= flags; } void Customize( wxUint32 flags ) { m_iFlags |= flags; }
@@ -637,9 +639,6 @@ protected:
// this is for the top level window // this is for the top level window
wxEvtHandler* m_toplevEvtHandler; wxEvtHandler* m_toplevEvtHandler;
// this is for the control in popup
wxEvtHandler* m_popupEvtHandler;
// main (ie. topmost) window of a composite control (default = this) // main (ie. topmost) window of a composite control (default = this)
wxWindow* m_mainCtrlWnd; wxWindow* m_mainCtrlWnd;
@@ -718,6 +717,10 @@ protected:
// is the text-area background colour overridden? // is the text-area background colour overridden?
bool m_hasTcBgCol; bool m_hasTcBgCol;
// flags used while popup is shown
bool m_beenInsidePopup;
bool m_blockEventsToPopup;
private: private:
void Init(); void Init();

View File

@@ -720,62 +720,17 @@ void wxComboCtrlBase::OnTextFocus(wxFocusEvent& event)
} }
// void wxComboCtrlBase::OnPopupMouseEvent( wxMouseEvent& event )
// This is pushed to the event handler queue of the control in popup.
//
class wxComboPopupEvtHandler : public wxEvtHandler
{
public:
wxComboPopupEvtHandler( wxComboCtrlBase* combo )
: wxEvtHandler()
{
m_combo = combo;
m_beenInside = false;
// Let's make it so that the popup control will not receive mouse
// events until mouse left button has been up.
m_blockEventsToPopup = true;
}
virtual ~wxComboPopupEvtHandler() { }
void OnMouseEvent( wxMouseEvent& event );
// Called from wxComboCtrlBase::OnPopupDismiss
void OnPopupDismiss()
{
m_beenInside = false;
m_blockEventsToPopup = true;
}
protected:
wxComboCtrlBase* m_combo;
bool m_beenInside;
bool m_blockEventsToPopup;
private:
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(wxComboPopupEvtHandler, wxEvtHandler)
EVT_MOUSE_EVENTS(wxComboPopupEvtHandler::OnMouseEvent)
wxEND_EVENT_TABLE()
void wxComboPopupEvtHandler::OnMouseEvent( wxMouseEvent& event )
{ {
wxPoint pt = event.GetPosition(); wxPoint pt = event.GetPosition();
wxSize sz = m_combo->GetPopupControl()->GetControl()->GetClientSize(); wxSize sz = GetPopupControl()->GetControl()->GetClientSize();
int evtType = event.GetEventType(); int evtType = event.GetEventType();
bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y; bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y;
bool relayToButton = false; bool relayToButton = false;
event.Skip(); event.Skip();
if ( !isInside || !m_combo->IsPopupShown() ) if ( !isInside || !IsPopupShown() )
{ {
// Mouse is outside the popup or popup is not actually shown (yet) // Mouse is outside the popup or popup is not actually shown (yet)
@@ -792,7 +747,7 @@ void wxComboPopupEvtHandler::OnMouseEvent( wxMouseEvent& event )
{ {
// Mouse is inside the popup, which is fully shown // Mouse is inside the popup, which is fully shown
m_beenInside = true; m_beenInsidePopup = true;
// Do not let the popup control respond to mouse events until // Do not let the popup control respond to mouse events until
// mouse press used to display the popup has been lifted. This // mouse press used to display the popup has been lifted. This
@@ -844,12 +799,12 @@ void wxComboPopupEvtHandler::OnMouseEvent( wxMouseEvent& event )
// //
if ( evtType == wxEVT_LEFT_UP ) if ( evtType == wxEVT_LEFT_UP )
{ {
if ( !m_combo->IsPopupShown() ) if ( !IsPopupShown() )
{ {
event.Skip(false); event.Skip(false);
relayToButton = true; relayToButton = true;
} }
else if ( !isInside && !m_beenInside ) else if ( !isInside && !m_beenInsidePopup )
{ {
// Popup is shown but the cursor is not inside, nor it has been // Popup is shown but the cursor is not inside, nor it has been
relayToButton = true; relayToButton = true;
@@ -858,14 +813,14 @@ void wxComboPopupEvtHandler::OnMouseEvent( wxMouseEvent& event )
if ( relayToButton ) if ( relayToButton )
{ {
wxWindow* btn = m_combo->GetButton(); wxWindow* btn = GetButton();
if ( btn ) if ( btn )
btn->GetEventHandler()->ProcessEvent(event); btn->GetEventHandler()->ProcessEvent(event);
else else
// Bypass the event handling mechanism. Using it would be // Bypass the event handling mechanism. Using it would be
// confusing for the platform-specific wxComboCtrl // confusing for the platform-specific wxComboCtrl
// implementations. // implementations.
m_combo->HandleButtonMouseEvent(event, 0); HandleButtonMouseEvent(event, 0);
} }
} }
@@ -918,8 +873,6 @@ void wxComboCtrlBase::Init()
m_text = NULL; m_text = NULL;
m_popupInterface = NULL; m_popupInterface = NULL;
m_popupEvtHandler = NULL;
#if INSTALL_TOPLEV_HANDLER #if INSTALL_TOPLEV_HANDLER
m_toplevEvtHandler = NULL; m_toplevEvtHandler = NULL;
#endif #endif
@@ -950,6 +903,12 @@ void wxComboCtrlBase::Init()
m_resetFocus = false; m_resetFocus = false;
m_hasTcBgCol = false; m_hasTcBgCol = false;
m_beenInsidePopup = false;
// Let's make it so that the popup control will not receive mouse
// events until mouse left button has been up.
m_blockEventsToPopup = true;
} }
bool wxComboCtrlBase::Create(wxWindow *parent, bool wxComboCtrlBase::Create(wxWindow *parent,
@@ -2038,7 +1997,6 @@ void wxComboCtrlBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event
void wxComboCtrlBase::CreatePopup() void wxComboCtrlBase::CreatePopup()
{ {
wxComboPopup* popupInterface = m_popupInterface; wxComboPopup* popupInterface = m_popupInterface;
wxWindow* popup;
if ( !m_winPopup ) if ( !m_winPopup )
{ {
@@ -2082,10 +2040,39 @@ void wxComboCtrlBase::CreatePopup()
} }
popupInterface->Create(m_winPopup); popupInterface->Create(m_winPopup);
m_popup = popup = popupInterface->GetControl(); m_popup = popupInterface->GetControl();
m_popupEvtHandler = new wxComboPopupEvtHandler(this); // Bind all mouse events, as used to be done by EVT_MOUSE_EVENTS() event
popup->PushEventHandler( m_popupEvtHandler ); // table macro, to this handler.
const wxEventTypeTag<wxMouseEvent> allMouseEventTypes[] =
{
wxEVT_LEFT_DOWN,
wxEVT_LEFT_UP,
wxEVT_LEFT_DCLICK,
wxEVT_MIDDLE_DOWN,
wxEVT_MIDDLE_UP,
wxEVT_MIDDLE_DCLICK,
wxEVT_RIGHT_DOWN,
wxEVT_RIGHT_UP,
wxEVT_RIGHT_DCLICK,
wxEVT_AUX1_DOWN,
wxEVT_AUX1_UP,
wxEVT_AUX1_DCLICK,
wxEVT_AUX2_DOWN,
wxEVT_AUX2_UP,
wxEVT_AUX2_DCLICK,
wxEVT_MOTION,
wxEVT_LEAVE_WINDOW,
wxEVT_ENTER_WINDOW,
wxEVT_MOUSEWHEEL,
wxEVT_MAGNIFY,
};
for ( size_t n = 0; n < WXSIZEOF(allMouseEventTypes); ++n )
{
m_popup->Bind(allMouseEventTypes[n],
&wxComboCtrlBase::OnPopupMouseEvent, this);
}
// This may be helpful on some platforms // This may be helpful on some platforms
// (eg. it bypasses a wxGTK popupwindow bug where // (eg. it bypasses a wxGTK popupwindow bug where
@@ -2100,11 +2087,6 @@ void wxComboCtrlBase::DestroyPopup()
{ {
HidePopup(true); HidePopup(true);
if ( m_popup )
m_popup->RemoveEventHandler(m_popupEvtHandler);
wxDELETE(m_popupEvtHandler);
if ( m_popupInterface ) if ( m_popupInterface )
{ {
// NB: DestroyPopup() performs 'delete this'. // NB: DestroyPopup() performs 'delete this'.
@@ -2450,8 +2432,9 @@ void wxComboCtrlBase::OnPopupDismiss(bool generateEvent)
// Inform popup control itself // Inform popup control itself
m_popupInterface->OnDismiss(); m_popupInterface->OnDismiss();
if ( m_popupEvtHandler ) // Reset popup-related flags.
((wxComboPopupEvtHandler*)m_popupEvtHandler)->OnPopupDismiss(); m_beenInsidePopup = false;
m_blockEventsToPopup = true;
#if INSTALL_TOPLEV_HANDLER #if INSTALL_TOPLEV_HANDLER
// Remove top level window event handler // Remove top level window event handler