From: Jaakko Salli Date: Sun, 27 Sep 2009 14:35:02 +0000 (+0000) Subject: Store property name and value in wxPropertyGridEvent, keep track of live event instan... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/644b283d6aa7740c0f4478945ca423279fe6d2da Store property name and value in wxPropertyGridEvent, keep track of live event instances, and clear property/grid information in them in wxPropertyGrid dtor. This allows application to relay events for later processing without fear of losing most relevant information within. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62168 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/propgrid/propgrid.h b/include/wx/propgrid/propgrid.h index e5cb9d741d..a8dbe52937 100644 --- a/include/wx/propgrid/propgrid.h +++ b/include/wx/propgrid/propgrid.h @@ -14,6 +14,7 @@ #if wxUSE_PROPGRID +#include "wx/thread.h" #include "wx/dcclient.h" #include "wx/scrolwin.h" #include "wx/tooltip.h" @@ -43,6 +44,14 @@ public: wxPGGlobalVarsClass(); ~wxPGGlobalVarsClass(); +#if wxUSE_THREAD + // Critical section for handling the globals. Generally it is not needed + // since GUI code is supposed to be in single thread. However, + // we do want the user to be able to convey wxPropertyGridEvents to other + // threads. + wxCriticalSection m_critSect; +#endif + // Used by advprops, but here to make things easier. wxString m_pDefaultImageWildcard; @@ -420,7 +429,7 @@ public: /** Returns reference to pending value. */ - const wxVariant& GetValue() const + wxVariant& GetValue() { wxASSERT(m_pValue); return *m_pValue; @@ -642,6 +651,7 @@ enum wxPG_KEYBOARD_ACTIONS class WXDLLIMPEXP_PROPGRID wxPropertyGrid : public wxScrolledWindow, public wxPropertyGridInterface { + friend class wxPropertyGridEvent; friend class wxPropertyGridPageState; friend class wxPropertyGridInterface; friend class wxPropertyGridManager; @@ -1851,6 +1861,9 @@ protected: // labels when properties use common values wxVector m_commonValues; + // array of live events + wxVector m_liveEvents; + // Which cv selection really sets value to unspecified? int m_cvUnspecified; @@ -2215,14 +2228,43 @@ public: */ void Veto( bool veto = true ) { m_wasVetoed = veto; } - /** Returns value that is about to be set for wxEVT_PG_CHANGING. + /** + Returns name of the associated property. + + @remarks Property name is stored in event, so it remains + accessible even after the associated property or + the property grid has been deleted. */ - const wxVariant& GetValue() const + wxString GetPropertyName() const { - wxASSERT_MSG( m_validationInfo, - "Only call GetValue from a handler " - "of event type that supports it" ); - return m_validationInfo->GetValue(); + return m_propertyName; + } + + /** + Returns value of the associated property. Works for all event + types, but for wxEVT_PG_CHANGING this member function returns + the value that is pending, so you can call Veto() if the + value is not satisfactory. + + @remarks Property value is stored in event, so it remains + accessible even after the associated property or + the property grid has been deleted. + */ + wxVariant GetPropertyValue() const + { + if ( m_validationInfo ) + return m_validationInfo->GetValue(); + return m_value; + } + + /** + Returns value of the associated property. + + @see GetPropertyValue + */ + wxVariant GetValue() const + { + return GetPropertyValue(); } /** @@ -2262,25 +2304,44 @@ public: bool WasVetoed() const { return m_wasVetoed; } /** Changes the associated property. */ - void SetProperty( wxPGProperty* p ) { m_property = p; } + void SetProperty( wxPGProperty* p ) + { + m_property = p; + if ( p ) + m_propertyName = p->GetName(); + } - void SetPropertyGrid( wxPropertyGrid* pg ) { m_pg = pg; } + void SetPropertyValue( wxVariant value ) + { + m_value = value; + } + + void SetPropertyGrid( wxPropertyGrid* pg ) + { + m_pg = pg; + OnPropertyGridSet(); + } void SetupValidationInfo() { wxASSERT(m_pg); wxASSERT( GetEventType() == wxEVT_PG_CHANGING ); m_validationInfo = &m_pg->GetValidationInfo(); + m_value = m_validationInfo->GetValue(); } private: void Init(); + void OnPropertyGridSet(); DECLARE_DYNAMIC_CLASS(wxPropertyGridEvent) wxPGProperty* m_property; wxPropertyGrid* m_pg; wxPGValidationInfo* m_validationInfo; + wxString m_propertyName; + wxVariant m_value; + unsigned int m_column; bool m_canVeto; diff --git a/interface/wx/propgrid/propgrid.h b/interface/wx/propgrid/propgrid.h index 665674620b..48f9c06cc7 100644 --- a/interface/wx/propgrid/propgrid.h +++ b/interface/wx/propgrid/propgrid.h @@ -270,7 +270,7 @@ public: /** Returns reference to pending value. */ - const wxVariant& GetValue() const; + wxVariant& GetValue(); /** Set validation failure behavior @@ -1076,9 +1076,30 @@ public: wxPGVFBFlags GetValidationFailureBehavior() const; /** - Returns value that is about to be set for wxEVT_PG_CHANGING. + Returns name of the associated property. + + @remarks Property name is stored in event, so it remains + accessible even after the associated property or + the property grid has been deleted. + */ + wxString GetPropertyName() const; + + /** + Returns value of the associated property. Works for all event + types, but for wxEVT_PG_CHANGING this member function returns + the value that is pending, so you can call Veto() if the + value is not satisfactory. + + @remarks Property value is stored in event, so it remains + accessible even after the associated property or + the property grid has been deleted. + */ + wxVariant GetPropertyValue() const + + /** + @see GetPropertyValue() */ - const wxVariant& GetValue() const; + wxVariant GetValue() const; /** Set if event can be vetoed. diff --git a/src/propgrid/propgrid.cpp b/src/propgrid/propgrid.cpp index 4eb8520799..e941c2a6c1 100644 --- a/src/propgrid/propgrid.cpp +++ b/src/propgrid/propgrid.cpp @@ -582,6 +582,20 @@ wxPropertyGrid::~wxPropertyGrid() { size_t i; +#if wxUSE_THREAD + wxCriticalSectionLocker(wxPGGlobalVars->m_critSect); +#endif + + // + // Remove grid and property pointers from live wxPropertyGridEvents. + for ( i=0; iSetPropertyGrid(NULL); + evt->SetProperty(NULL); + } + m_liveEvents.clear(); + if ( m_processedEvent ) { // All right... we are being deleted while wxPropertyGrid event @@ -592,7 +606,7 @@ wxPropertyGrid::~wxPropertyGrid() m_processedEvent->StopPropagation(); // Let's use wxMessageBox to make the message appear more - // reliably (and *before* the crash can happend). + // reliably (and *before* the crash can happen). ::wxMessageBox("wxPropertyGrid was being destroyed in an event " "generated by it. This usually leads to a crash " "so it is recommended to destroy the control " @@ -4399,25 +4413,26 @@ bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, evt.SetEventObject(m_eventObject); evt.SetProperty(p); evt.SetColumn(column); - if ( pValue ) + if ( eventType == wxEVT_PG_CHANGING ) { + wxASSERT( pValue ); evt.SetCanVeto(true); - evt.SetupValidationInfo(); m_validationInfo.m_pValue = pValue; + evt.SetupValidationInfo(); } - else if ( !(selFlags & wxPG_SEL_NOVALIDATE) ) + else { - evt.SetCanVeto(true); + if ( p ) + evt.SetPropertyValue(p->GetValue()); + + if ( !(selFlags & wxPG_SEL_NOVALIDATE) ) + evt.SetCanVeto(true); } m_processedEvent = &evt; - - wxEvtHandler* evtHandler = m_eventObject->GetEventHandler(); - + m_eventObject->HandleWindowEvent(evt); m_processedEvent = NULL; - evtHandler->ProcessEvent(evt); - return evt.WasVetoed(); } @@ -5860,6 +5875,7 @@ wxPropertyGridEvent::wxPropertyGridEvent(const wxPropertyGridEvent& event) m_eventType = event.GetEventType(); m_eventObject = event.m_eventObject; m_pg = event.m_pg; + OnPropertyGridSet(); m_property = event.m_property; m_validationInfo = event.m_validationInfo; m_canVeto = event.m_canVeto; @@ -5868,8 +5884,40 @@ wxPropertyGridEvent::wxPropertyGridEvent(const wxPropertyGridEvent& event) // ----------------------------------------------------------------------- +void wxPropertyGridEvent::OnPropertyGridSet() +{ + if ( !m_pg ) + return; + +#if wxUSE_THREAD + wxCriticalSectionLocker(wxPGGlobalVars->m_critSect); +#endif + m_pg->m_liveEvents.push_back(this); +} + +// ----------------------------------------------------------------------- + wxPropertyGridEvent::~wxPropertyGridEvent() { + if ( m_pg ) + { + #if wxUSE_THREAD + wxCriticalSectionLocker(wxPGGlobalVars->m_critSect); + #endif + + // Use iterate from the back since it is more likely that the event + // being desroyed is at the end of the array. + wxVector& liveEvents = m_pg->m_liveEvents; + + for ( int i = liveEvents.size()-1; i >= 0; i-- ) + { + if ( liveEvents[i] == this ) + { + liveEvents.erase(liveEvents.begin() + i); + break; + } + } + } } // -----------------------------------------------------------------------