From 8b7fdc5e5bf18fb34726b16cf106550aef48271c Mon Sep 17 00:00:00 2001 From: Ian McInerney Date: Thu, 9 Jul 2020 17:56:43 +0100 Subject: [PATCH 1/2] Close the cell editor when the editors combobox is closed Closes #16404 --- include/wx/generic/grideditors.h | 3 +++ src/generic/grideditors.cpp | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/wx/generic/grideditors.h b/include/wx/generic/grideditors.h index ad6e90f19c..a6bdbc6377 100644 --- a/include/wx/generic/grideditors.h +++ b/include/wx/generic/grideditors.h @@ -335,6 +335,9 @@ public: protected: wxComboBox *Combo() const { return (wxComboBox *)m_control; } + void onComboCloseUp(wxCommandEvent& evt); + void onComboDropDown(wxCommandEvent& evt); + wxString m_value; wxArrayString m_choices; bool m_allowOthers; diff --git a/src/generic/grideditors.cpp b/src/generic/grideditors.cpp index 00d1aa8918..29dbaaa571 100644 --- a/src/generic/grideditors.cpp +++ b/src/generic/grideditors.cpp @@ -1580,7 +1580,12 @@ void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid) wxGridCellEditorEvtHandler* evtHandler = NULL; if (m_control) + { + // These event handlers are needed to properly dismiss the editor when the popup is closed + m_control->Bind(wxEVT_COMBOBOX_DROPDOWN, &wxGridCellChoiceEditor::onComboDropDown, this); + m_control->Bind(wxEVT_COMBOBOX_CLOSEUP, &wxGridCellChoiceEditor::onComboCloseUp, this); evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler); + } // Don't immediately end if we get a kill focus event within BeginEdit if (evtHandler) @@ -1679,6 +1684,35 @@ wxString wxGridCellChoiceEditor::GetValue() const return Combo()->GetValue(); } +void wxGridCellChoiceEditor::onComboDropDown(wxCommandEvent& WXUNUSED(evt)) +{ + wxGridCellEditorEvtHandler* evtHandler = wxDynamicCast(m_control->GetEventHandler(), + wxGridCellEditorEvtHandler); + + if ( !evtHandler ) + return; + + // Once the combobox is dropped, reset the flag to allow the focus-loss handler + // to function and close the editor. + evtHandler->SetInSetFocus(false); +} + +void wxGridCellChoiceEditor::onComboCloseUp(wxCommandEvent& WXUNUSED(evt)) +{ + wxGridCellEditorEvtHandler* evtHandler = wxDynamicCast(m_control->GetEventHandler(), + wxGridCellEditorEvtHandler); + + if ( !evtHandler ) + return; + + // Forward the combobox close up event to the cell event handler as a focus kill event + // so that the grid editor is dismissed when the combox closes, otherwise it leaves the + // dropdown arrow visible in the cell. + wxFocusEvent event(wxEVT_KILL_FOCUS, m_control->GetId()); + event.SetEventObject(m_control); + evtHandler->ProcessEvent(event); +} + #endif // wxUSE_COMBOBOX #if wxUSE_COMBOBOX From b256aa6956b04db9ce8b58e983978ece7d116e16 Mon Sep 17 00:00:00 2001 From: Ian McInerney Date: Mon, 13 Jul 2020 00:32:06 +0100 Subject: [PATCH 2/2] Replace wxEVT_GRID_HIDE_EDITOR usage with CallAfter This simplifies the code by removing the need for a special event, and also means the combox popup handler is no longer needed to reset the inSetFocus flag for the closing handler. --- include/wx/generic/grid.h | 1 - include/wx/generic/grideditors.h | 5 +-- include/wx/generic/private/grid.h | 4 --- src/generic/grid.cpp | 6 ---- src/generic/grideditors.cpp | 53 ++++++++++--------------------- 5 files changed, 20 insertions(+), 49 deletions(-) diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 093063eb2a..5f081ab92b 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -2827,7 +2827,6 @@ protected: void OnKeyDown( wxKeyEvent& ); void OnKeyUp( wxKeyEvent& ); void OnChar( wxKeyEvent& ); - void OnHideEditor( wxCommandEvent& ); bool SetCurrentCell( const wxGridCellCoords& coords ); diff --git a/include/wx/generic/grideditors.h b/include/wx/generic/grideditors.h index a6bdbc6377..4510d31944 100644 --- a/include/wx/generic/grideditors.h +++ b/include/wx/generic/grideditors.h @@ -27,6 +27,8 @@ public: { } + void DismissEditor(); + void OnKillFocus(wxFocusEvent& event); void OnKeyDown(wxKeyEvent& event); void OnChar(wxKeyEvent& event); @@ -335,8 +337,7 @@ public: protected: wxComboBox *Combo() const { return (wxComboBox *)m_control; } - void onComboCloseUp(wxCommandEvent& evt); - void onComboDropDown(wxCommandEvent& evt); + void OnComboCloseUp(wxCommandEvent& evt); wxString m_value; wxArrayString m_choices; diff --git a/include/wx/generic/private/grid.h b/include/wx/generic/private/grid.h index 7faabcd7c3..acf0b68207 100644 --- a/include/wx/generic/private/grid.h +++ b/include/wx/generic/private/grid.h @@ -17,10 +17,6 @@ #include "wx/headerctrl.h" -// Internally used (and hence intentionally not exported) event telling wxGrid -// to hide the currently shown editor. -wxDECLARE_EVENT( wxEVT_GRID_HIDE_EDITOR, wxCommandEvent ); - // ---------------------------------------------------------------------------- // array classes // ---------------------------------------------------------------------------- diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index a9ff705bc4..1071c7cd56 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -2519,7 +2519,6 @@ wxBEGIN_EVENT_TABLE( wxGrid, wxScrolledCanvas ) EVT_KEY_DOWN( wxGrid::OnKeyDown ) EVT_KEY_UP( wxGrid::OnKeyUp ) EVT_CHAR ( wxGrid::OnChar ) - EVT_COMMAND(wxID_ANY, wxEVT_GRID_HIDE_EDITOR, wxGrid::OnHideEditor ) wxEND_EVENT_TABLE() bool wxGrid::Create(wxWindow *parent, wxWindowID id, @@ -7543,11 +7542,6 @@ void wxGrid::DoSaveEditControlValue() } } -void wxGrid::OnHideEditor(wxCommandEvent& WXUNUSED(event)) -{ - DisableCellEditControl(); -} - // // ------ Grid location functions // Note that all of these functions work with the logical coordinates of diff --git a/src/generic/grideditors.cpp b/src/generic/grideditors.cpp index 29dbaaa571..7a328d9b97 100644 --- a/src/generic/grideditors.cpp +++ b/src/generic/grideditors.cpp @@ -66,12 +66,19 @@ // implementation // ============================================================================ -wxDEFINE_EVENT( wxEVT_GRID_HIDE_EDITOR, wxCommandEvent ); - // ---------------------------------------------------------------------------- // wxGridCellEditorEvtHandler // ---------------------------------------------------------------------------- +void wxGridCellEditorEvtHandler::DismissEditor() +{ + // Tell the grid to dismiss the control but don't do it immediately as it + // could result in the editor being destroyed right now and a crash in the + // code searching for the next event handler, so tell the grid to close it + // after this event is processed. + m_grid->CallAfter(&wxGrid::DisableCellEditControl); +} + void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent& event) { // We must let the native control have this event so in any case don't mark @@ -82,16 +89,7 @@ void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent& event) if (m_inSetFocus) return; - // Tell the grid to dismiss the control but don't do it immediately as it - // could result in the editor being destroyed right now and a crash in the - // code searching for the next event handler, so post an event asking the - // grid to do it slightly later instead. - - // FIXME-VC6: Once we drop support for VC6, we should use a simpler - // m_grid->CallAfter(&wxGrid::DisableCellEditControl) and get - // rid of wxEVT_GRID_HIDE_EDITOR entirely. - m_grid->GetEventHandler()-> - AddPendingEvent(wxCommandEvent(wxEVT_GRID_HIDE_EDITOR)); + DismissEditor(); } void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) @@ -100,7 +98,7 @@ void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event) { case WXK_ESCAPE: m_editor->Reset(); - m_grid->DisableCellEditControl(); + DismissEditor(); break; case WXK_TAB: @@ -1581,9 +1579,8 @@ void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid) wxGridCellEditorEvtHandler* evtHandler = NULL; if (m_control) { - // These event handlers are needed to properly dismiss the editor when the popup is closed - m_control->Bind(wxEVT_COMBOBOX_DROPDOWN, &wxGridCellChoiceEditor::onComboDropDown, this); - m_control->Bind(wxEVT_COMBOBOX_CLOSEUP, &wxGridCellChoiceEditor::onComboCloseUp, this); + // This event handler is needed to properly dismiss the editor when the popup is closed + m_control->Bind(wxEVT_COMBOBOX_CLOSEUP, &wxGridCellChoiceEditor::OnComboCloseUp, this); evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler); } @@ -1684,7 +1681,7 @@ wxString wxGridCellChoiceEditor::GetValue() const return Combo()->GetValue(); } -void wxGridCellChoiceEditor::onComboDropDown(wxCommandEvent& WXUNUSED(evt)) +void wxGridCellChoiceEditor::OnComboCloseUp(wxCommandEvent& WXUNUSED(evt)) { wxGridCellEditorEvtHandler* evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler); @@ -1692,25 +1689,9 @@ void wxGridCellChoiceEditor::onComboDropDown(wxCommandEvent& WXUNUSED(evt)) if ( !evtHandler ) return; - // Once the combobox is dropped, reset the flag to allow the focus-loss handler - // to function and close the editor. - evtHandler->SetInSetFocus(false); -} - -void wxGridCellChoiceEditor::onComboCloseUp(wxCommandEvent& WXUNUSED(evt)) -{ - wxGridCellEditorEvtHandler* evtHandler = wxDynamicCast(m_control->GetEventHandler(), - wxGridCellEditorEvtHandler); - - if ( !evtHandler ) - return; - - // Forward the combobox close up event to the cell event handler as a focus kill event - // so that the grid editor is dismissed when the combox closes, otherwise it leaves the + // Close the grid editor when the combobox closes, otherwise it leaves the // dropdown arrow visible in the cell. - wxFocusEvent event(wxEVT_KILL_FOCUS, m_control->GetId()); - event.SetEventObject(m_control); - evtHandler->ProcessEvent(event); + evtHandler->DismissEditor(); } #endif // wxUSE_COMBOBOX @@ -1864,7 +1845,7 @@ struct wxGridCellDateEditorKeyHandler case WXK_RETURN: case WXK_NUMPAD_ENTER: - wxPostEvent(m_handler, wxCommandEvent(wxEVT_GRID_HIDE_EDITOR)); + m_handler->DismissEditor(); event.Skip(); break;