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:
@@ -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<wxPGCommonValue*> m_commonValues;
|
||||
|
||||
// array of live events
|
||||
wxVector<wxPropertyGridEvent*> 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_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;
|
||||
|
@@ -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.
|
||||
*/
|
||||
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.
|
||||
|
@@ -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; i<m_liveEvents.size(); i++ )
|
||||
{
|
||||
wxPropertyGridEvent* evt = m_liveEvents[i];
|
||||
evt->SetPropertyGrid(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
|
||||
{
|
||||
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<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user