const wxString& name )
{
- if ( !(style&wxBORDER_MASK) )
- style |= wxSIMPLE_BORDER;
+ if (!(style&wxBORDER_MASK))
+ {
+ style |= wxBORDER_THEME;
+ }
style |= wxVSCROLL;
m_labelEditorProperty = NULL;
m_eventObject = this;
m_curFocused = NULL;
+ m_processedEvent = NULL;
m_sortFunction = NULL;
m_inDoPropertyChanged = 0;
m_inCommitChangesFromEditor = 0;
m_timeCreated = ::wxGetLocalTimeMillis();
m_canvas = new wxPGCanvas();
- m_canvas->Create(this, 1, wxPoint(0, 0), GetClientSize(),
+ m_canvas->Create(this, wxID_ANY, wxPoint(0, 0), GetClientSize(),
wxWANTS_CHARS | wxCLIP_CHILDREN);
m_canvas->SetBackgroundStyle( wxBG_STYLE_CUSTOM );
{
size_t i;
+#if wxUSE_THREADS
+ 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
+ // is being sent. Make sure that event propagates as little
+ // as possible (although usually this is not enough to prevent
+ // a crash).
+ m_processedEvent->Skip(false);
+ m_processedEvent->StopPropagation();
+
+ // Let's use wxMessageBox to make the message appear more
+ // 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 "
+ "at idle time instead.");
+ }
+
DoSelectProperty(NULL, wxPG_SEL_NOVALIDATE|wxPG_SEL_DONT_SEND_EVENT);
// This should do prevent things from going too badly wrong
// Delete common value records
for ( i=0; i<m_commonValues.size(); i++ )
{
- delete GetCommonValue(i);
+ // Use temporary variable to work around possible strange VC6 (asserts because m_size is zero)
+ wxPGCommonValue* value = m_commonValues[i];
+ delete value;
}
}
DoClearSelection();
bool res = wxScrolledWindow::SetFont( font );
- if ( res && GetParent()) // may not have been Create()ed yet
+ if ( res && GetParent()) // may not have been Create()ed yet if SetFont called from SetWindowVariant
{
CalculateFontAndBitmapStuff( m_vspacing );
Refresh();
int y2 = y + lh;
+#ifdef __WXMSW__
// Margin Edge
- dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+ // Modified by JACS to not draw a margin if wxPG_HIDE_MARGIN is specified, since it
+ // looks better, at least under Windows when we have a themed border (the themed-window-specific
+ // whitespace between the real border and the propgrid margin exacerbates the double-border look).
+
+ // Is this or its parent themed?
+ bool suppressMarginEdge = (GetWindowStyle() & wxPG_HIDE_MARGIN) &&
+ (((GetWindowStyle() & wxBORDER_MASK) == wxBORDER_THEME) ||
+ (((GetWindowStyle() & wxBORDER_MASK) == wxBORDER_NONE) && ((GetParent()->GetWindowStyle() & wxBORDER_MASK) == wxBORDER_THEME)));
+#else
+ bool suppressMarginEdge = false;
+#endif
+ if (!suppressMarginEdge)
+ dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+ else
+ {
+ // Blank out the margin edge
+ dc.SetPen(wxPen(GetBackgroundColour()));
+ dc.DrawLine( greyDepthX, y, greyDepthX, y2 );
+ dc.SetPen( linepen );
+ }
// Splitters
unsigned int si;
// Somehow, event is handled after property has been deselected.
// Possibly, but very rare.
- if ( !selected || selected->HasFlag(wxPG_PROP_BEING_DELETED) )
+ if ( !selected ||
+ selected->HasFlag(wxPG_PROP_BEING_DELETED) ||
+ // Also don't handle editor event if wxEVT_PG_CHANGED or
+ // similar is currently doing something (showing a
+ // message box, for instance).
+ m_processedEvent )
return;
if ( m_iFlags & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT )
m_width = width;
m_height = height;
- m_canvas->SetSize( x, y );
+ // Explicitly pass the position - works around a bug in wxWidgets when the property grid
+ // has a native XP border and a contained window creeps up-and-left when size is set without
+ // the position.
+ m_canvas->SetSize( 0, 0, x, y );
m_pState->CheckColumnWidths();
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());
- wxEvtHandler* evtHandler = m_eventObject->GetEventHandler();
+ if ( !(selFlags & wxPG_SEL_NOVALIDATE) )
+ evt.SetCanVeto(true);
+ }
- evtHandler->ProcessEvent(evt);
+ m_processedEvent = &evt;
+ m_eventObject->HandleWindowEvent(evt);
+ m_processedEvent = NULL;
return evt.WasVetoed();
}
event.LeftIsDown() &&
m_propHover &&
GetSelection() &&
+ columnHit != 1 &&
!state->DoIsPropertySelected(m_propHover) )
{
// Additional requirement is that the hovered property
void wxPropertyGrid::ClearActionTriggers( int action )
{
wxPGHashMapI2I::iterator it;
+ bool didSomething;
- for ( it = m_actionTriggers.begin(); it != m_actionTriggers.end(); ++it )
+ do
{
- if ( it->second == action )
+ didSomething = false;
+
+ for ( it = m_actionTriggers.begin();
+ it != m_actionTriggers.end();
+ it++ )
{
- m_actionTriggers.erase(it);
+ if ( it->second == action )
+ {
+ m_actionTriggers.erase(it);
+ didSomething = true;
+ break;
+ }
}
}
+ while ( didSomething );
}
void wxPropertyGrid::HandleKeyEvent( wxKeyEvent &event, bool fromChild )
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;
// -----------------------------------------------------------------------
+void wxPropertyGridEvent::OnPropertyGridSet()
+{
+ if ( !m_pg )
+ return;
+
+#if wxUSE_THREADS
+ wxCriticalSectionLocker(wxPGGlobalVars->m_critSect);
+#endif
+ m_pg->m_liveEvents.push_back(this);
+}
+
+// -----------------------------------------------------------------------
+
wxPropertyGridEvent::~wxPropertyGridEvent()
{
+ if ( m_pg )
+ {
+ #if wxUSE_THREADS
+ 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;
+ }
+ }
+ }
}
// -----------------------------------------------------------------------