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
This commit is contained in:
Jaakko Salli
2009-09-27 14:35:02 +00:00
parent 9867e3e498
commit 644b283d6a
3 changed files with 152 additions and 22 deletions

View File

@@ -14,6 +14,7 @@
#if wxUSE_PROPGRID #if wxUSE_PROPGRID
#include "wx/thread.h"
#include "wx/dcclient.h" #include "wx/dcclient.h"
#include "wx/scrolwin.h" #include "wx/scrolwin.h"
#include "wx/tooltip.h" #include "wx/tooltip.h"
@@ -43,6 +44,14 @@ public:
wxPGGlobalVarsClass(); wxPGGlobalVarsClass();
~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. // Used by advprops, but here to make things easier.
wxString m_pDefaultImageWildcard; wxString m_pDefaultImageWildcard;
@@ -420,7 +429,7 @@ public:
/** /**
Returns reference to pending value. Returns reference to pending value.
*/ */
const wxVariant& GetValue() const wxVariant& GetValue()
{ {
wxASSERT(m_pValue); wxASSERT(m_pValue);
return *m_pValue; return *m_pValue;
@@ -642,6 +651,7 @@ enum wxPG_KEYBOARD_ACTIONS
class WXDLLIMPEXP_PROPGRID class WXDLLIMPEXP_PROPGRID
wxPropertyGrid : public wxScrolledWindow, public wxPropertyGridInterface wxPropertyGrid : public wxScrolledWindow, public wxPropertyGridInterface
{ {
friend class wxPropertyGridEvent;
friend class wxPropertyGridPageState; friend class wxPropertyGridPageState;
friend class wxPropertyGridInterface; friend class wxPropertyGridInterface;
friend class wxPropertyGridManager; friend class wxPropertyGridManager;
@@ -1851,6 +1861,9 @@ protected:
// labels when properties use common values // labels when properties use common values
wxVector<wxPGCommonValue*> m_commonValues; wxVector<wxPGCommonValue*> m_commonValues;
// array of live events
wxVector<wxPropertyGridEvent*> m_liveEvents;
// Which cv selection really sets value to unspecified? // Which cv selection really sets value to unspecified?
int m_cvUnspecified; int m_cvUnspecified;
@@ -2215,14 +2228,43 @@ public:
*/ */
void Veto( bool veto = true ) { m_wasVetoed = veto; } 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, return m_propertyName;
"Only call GetValue from a handler " }
"of event type that supports it" );
return m_validationInfo->GetValue(); /**
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; } bool WasVetoed() const { return m_wasVetoed; }
/** Changes the associated property. */ /** 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() void SetupValidationInfo()
{ {
wxASSERT(m_pg); wxASSERT(m_pg);
wxASSERT( GetEventType() == wxEVT_PG_CHANGING ); wxASSERT( GetEventType() == wxEVT_PG_CHANGING );
m_validationInfo = &m_pg->GetValidationInfo(); m_validationInfo = &m_pg->GetValidationInfo();
m_value = m_validationInfo->GetValue();
} }
private: private:
void Init(); void Init();
void OnPropertyGridSet();
DECLARE_DYNAMIC_CLASS(wxPropertyGridEvent) DECLARE_DYNAMIC_CLASS(wxPropertyGridEvent)
wxPGProperty* m_property; wxPGProperty* m_property;
wxPropertyGrid* m_pg; wxPropertyGrid* m_pg;
wxPGValidationInfo* m_validationInfo; wxPGValidationInfo* m_validationInfo;
wxString m_propertyName;
wxVariant m_value;
unsigned int m_column; unsigned int m_column;
bool m_canVeto; bool m_canVeto;

View File

@@ -270,7 +270,7 @@ public:
/** /**
Returns reference to pending value. Returns reference to pending value.
*/ */
const wxVariant& GetValue() const; wxVariant& GetValue();
/** Set validation failure behavior /** Set validation failure behavior
@@ -1076,9 +1076,30 @@ public:
wxPGVFBFlags GetValidationFailureBehavior() const; 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.
*/ */
const wxVariant& GetValue() const; 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()
*/
wxVariant GetValue() const;
/** /**
Set if event can be vetoed. Set if event can be vetoed.

View File

@@ -582,6 +582,20 @@ wxPropertyGrid::~wxPropertyGrid()
{ {
size_t i; size_t i;
#if wxUSE_THREAD
wxCriticalSectionLocker(wxPGGlobalVars->m_critSect);
#endif
//
// Remove grid and property pointers from live wxPropertyGridEvents.
for ( i=0; i<m_liveEvents.size(); i++ )
{
wxPropertyGridEvent* evt = m_liveEvents[i];
evt->SetPropertyGrid(NULL);
evt->SetProperty(NULL);
}
m_liveEvents.clear();
if ( m_processedEvent ) if ( m_processedEvent )
{ {
// All right... we are being deleted while wxPropertyGrid event // All right... we are being deleted while wxPropertyGrid event
@@ -592,7 +606,7 @@ wxPropertyGrid::~wxPropertyGrid()
m_processedEvent->StopPropagation(); m_processedEvent->StopPropagation();
// Let's use wxMessageBox to make the message appear more // 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 " ::wxMessageBox("wxPropertyGrid was being destroyed in an event "
"generated by it. This usually leads to a crash " "generated by it. This usually leads to a crash "
"so it is recommended to destroy the control " "so it is recommended to destroy the control "
@@ -4399,25 +4413,26 @@ bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p,
evt.SetEventObject(m_eventObject); evt.SetEventObject(m_eventObject);
evt.SetProperty(p); evt.SetProperty(p);
evt.SetColumn(column); evt.SetColumn(column);
if ( pValue ) if ( eventType == wxEVT_PG_CHANGING )
{ {
wxASSERT( pValue );
evt.SetCanVeto(true); evt.SetCanVeto(true);
evt.SetupValidationInfo();
m_validationInfo.m_pValue = pValue; 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; m_processedEvent = &evt;
m_eventObject->HandleWindowEvent(evt);
wxEvtHandler* evtHandler = m_eventObject->GetEventHandler();
m_processedEvent = NULL; m_processedEvent = NULL;
evtHandler->ProcessEvent(evt);
return evt.WasVetoed(); return evt.WasVetoed();
} }
@@ -5860,6 +5875,7 @@ wxPropertyGridEvent::wxPropertyGridEvent(const wxPropertyGridEvent& event)
m_eventType = event.GetEventType(); m_eventType = event.GetEventType();
m_eventObject = event.m_eventObject; m_eventObject = event.m_eventObject;
m_pg = event.m_pg; m_pg = event.m_pg;
OnPropertyGridSet();
m_property = event.m_property; m_property = event.m_property;
m_validationInfo = event.m_validationInfo; m_validationInfo = event.m_validationInfo;
m_canVeto = event.m_canVeto; 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() 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<wxPropertyGridEvent*>& liveEvents = m_pg->m_liveEvents;
for ( int i = liveEvents.size()-1; i >= 0; i-- )
{
if ( liveEvents[i] == this )
{
liveEvents.erase(liveEvents.begin() + i);
break;
}
}
}
} }
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------