From 1e3e5b72530d51d2465c8ba876869cfbb8d74b50 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 4 Feb 2018 22:40:51 +0100 Subject: [PATCH] Send wxEVT_DATAVIEW_ITEM_EDITING_DONE after cancelling too Previously this event was not sent at all if editing the item was cancelled, e.g. by pressing Esc. Do send it now from the generic implementation and update the sample to show this event. See #17835. --- docs/changes.txt | 1 + include/wx/dvrenderers.h | 3 +++ samples/dataview/dataview.cpp | 6 ++++- src/common/datavcmn.cpp | 51 +++++++++++++++++++++++++---------- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 6ad30469d8..8520be4207 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -182,6 +182,7 @@ All (GUI): - Generate wxEVT_SEARCH on Enter under all platforms. - Extend wxRendererNative::DrawGauge() to work for vertical gauges too. - Add wxHD_BITMAP_ON_RIGHT style to wxHeaderCtrl. +- Send wxEVT_DATAVIEW_ITEM_EDITING_DONE when editing was cancelled too. wxGTK: diff --git a/include/wx/dvrenderers.h b/include/wx/dvrenderers.h index 0d2615b659..c1230cafcc 100644 --- a/include/wx/dvrenderers.h +++ b/include/wx/dvrenderers.h @@ -259,6 +259,9 @@ protected: wxDataViewCtrl* GetView() const; private: + // Common part of {Cancel,Finish}Editing(). + bool DoFinishOrCancelEditing(bool cancelled); + // Called from {Called,Finish}Editing() and dtor to cleanup m_editorCtrl void DestroyEditControl(); diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 64e89e7b71..240fc74d40 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -1227,7 +1227,11 @@ void MyFrame::OnEditingStarted( wxDataViewEvent &event ) void MyFrame::OnEditingDone( wxDataViewEvent &event ) { wxString title = m_music_model->GetTitle( event.GetItem() ); - wxLogMessage( "wxEVT_DATAVIEW_ITEM_EDITING_DONE, Item: %s", title ); + wxLogMessage("wxEVT_DATAVIEW_ITEM_EDITING_DONE, Item: %s, new value %s", + title, + event.IsEditCancelled() + ? wxString("unavailable because editing was cancelled") + : event.GetValue().GetString()); } void MyFrame::OnExpanded( wxDataViewEvent &event ) diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp index a7d7597fff..dcbc5cd101 100644 --- a/src/common/datavcmn.cpp +++ b/src/common/datavcmn.cpp @@ -766,44 +766,67 @@ void wxDataViewRendererBase::DestroyEditControl() void wxDataViewRendererBase::CancelEditing() { - if (!m_editorCtrl) - return; - - DestroyEditControl(); + DoFinishOrCancelEditing(true); } bool wxDataViewRendererBase::FinishEditing() +{ + return DoFinishOrCancelEditing(false); +} + +bool wxDataViewRendererBase::DoFinishOrCancelEditing(bool cancelled) { if (!m_editorCtrl) return true; - // Try to get the value, normally we should succeed but if we fail, don't - // return immediately, we still need to destroy the edit control. + bool gotValue = false; + wxVariant value; - const bool gotValue = GetValueFromEditorCtrl(m_editorCtrl, value); + if ( !cancelled ) + { + if ( GetValueFromEditorCtrl(m_editorCtrl, value) ) + { + // This is the normal case and we will use this value below (if it + // passes validation). + gotValue = true; + } + //else: Not really supposed to happen, but still proceed with + // destroying the edit control if it does. + } wxDataViewColumn* const column = GetOwner(); wxDataViewCtrl* const dv_ctrl = column->GetOwner(); DestroyEditControl(); - dv_ctrl->GetMainWindow()->SetFocus(); + // If we're cancelled, it can be because focus was switched elsewhere, + // don't bring it back here. + if ( !cancelled ) + dv_ctrl->GetMainWindow()->SetFocus(); - if ( !gotValue ) - return false; + if ( gotValue ) + { + if ( !Validate(value) ) + { + // Invalid value can't be used, so if it's the same as if we hadn't + // got it in the first place. + gotValue = false; + } + } - bool isValid = Validate(value); unsigned int col = GetOwner()->GetModelColumn(); // Now we should send Editing Done event wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EDITING_DONE, dv_ctrl, column, m_item); - event.SetValue( value ); - if ( !isValid ) + if ( gotValue ) + event.SetValue(value); + else event.SetEditCancelled(); + dv_ctrl->GetEventHandler()->ProcessEvent( event ); bool accepted = false; - if ( isValid && event.IsAllowed() ) + if ( gotValue && event.IsAllowed() ) { dv_ctrl->GetModel()->ChangeValue(value, m_item, col); accepted = true;