X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/08c1613f889a3239c6392b4828c07dd4a00bac22..b80fdc029995a0c2ce04910e26d652292c64d7bc:/src/propgrid/propgrid.cpp diff --git a/src/propgrid/propgrid.cpp b/src/propgrid/propgrid.cpp index 45fd19645c..4eb8520799 100644 --- a/src/propgrid/propgrid.cpp +++ b/src/propgrid/propgrid.cpp @@ -64,10 +64,6 @@ #include "wx/timer.h" #include "wx/dcbuffer.h" -#ifdef __WXMSW__ - #include "wx/msw/private.h" -#endif - // Two pics for the expand / collapse buttons. // Files are not supplied with this project (since it is // recommended to use either custom or native rendering). @@ -398,8 +394,10 @@ bool wxPropertyGrid::Create( wxWindow *parent, const wxString& name ) { - if ( !(style&wxBORDER_MASK) ) - style |= wxSIMPLE_BORDER; + if (!(style&wxBORDER_MASK)) + { + style |= wxBORDER_THEME; + } style |= wxVSCROLL; @@ -435,6 +433,7 @@ void wxPropertyGrid::Init1() m_labelEditorProperty = NULL; m_eventObject = this; m_curFocused = NULL; + m_processedEvent = NULL; m_sortFunction = NULL; m_inDoPropertyChanged = 0; m_inCommitChangesFromEditor = 0; @@ -563,7 +562,7 @@ void wxPropertyGrid::Init2() 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 ); @@ -583,6 +582,23 @@ wxPropertyGrid::~wxPropertyGrid() { size_t i; + 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 happend). + ::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 @@ -621,7 +637,9 @@ wxPropertyGrid::~wxPropertyGrid() // Delete common value records for ( i=0; im_editableColumns; + + if ( editable ) + { + cols.push_back(column); + } + else + { + for ( int i = cols.size() - 1; i > 0; i-- ) + { + if ( cols[i] == (int)column ) + cols.erase( cols.begin() + i ); + } + } +} + +// ----------------------------------------------------------------------- + void wxPropertyGrid::DoBeginLabelEdit( unsigned int colIndex, int selFlags ) { @@ -1130,7 +1171,15 @@ wxSize wxPropertyGrid::DoGetBestSize() const 10 ); - const wxSize sz = wxSize(60, lineHeight*numLines + 40); + wxClientDC dc(const_cast(this)); + int width = m_marginWidth; + for ( unsigned int i = 0; i < m_pState->m_colWidths.size(); i++ ) + { + width += m_pState->GetColumnFitWidth(dc, m_pState->DoGetRoot(), i, true); + } + + const wxSize sz = wxSize(width, lineHeight*numLines + 40); + CacheBestSize(sz); return sz; } @@ -1406,7 +1455,7 @@ bool wxPropertyGrid::SetFont( const wxFont& font ) 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(); @@ -2120,8 +2169,28 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc, 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; @@ -3836,18 +3905,6 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) if ( (p->m_flags & wxPG_PROP_MODIFIED) && (m_windowStyle & wxPG_BOLD_MODIFIED) ) SetCurControlBoldFont(); - // - // Fix TextCtrl indentation - #if defined(__WXMSW__) && !defined(__WXWINCE__) - wxTextCtrl* tc = NULL; - if ( primaryCtrl->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ) - tc = ((wxOwnerDrawnComboBox*)primaryCtrl)->GetTextCtrl(); - else - tc = wxDynamicCast(primaryCtrl, wxTextCtrl); - if ( tc ) - ::SendMessage(GetHwndOf(tc), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0)); - #endif - // Store x relative to splitter (we'll need it). m_ctrlXAdjust = m_wndEditor->GetPosition().x - splitterX; @@ -4230,7 +4287,10 @@ void wxPropertyGrid::RecalculateVirtualSize( int forceXPos ) 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(); @@ -4350,8 +4410,12 @@ bool wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, evt.SetCanVeto(true); } + m_processedEvent = &evt; + wxEvtHandler* evtHandler = m_eventObject->GetEventHandler(); + m_processedEvent = NULL; + evtHandler->ProcessEvent(evt); return evt.WasVetoed(); @@ -4783,13 +4847,33 @@ bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event // // Multi select by dragging // - if ( GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION && + if ( (GetExtraStyle() & wxPG_EX_MULTIPLE_SELECTION) && event.LeftIsDown() && m_propHover && GetSelection() && + columnHit != 1 && !state->DoIsPropertySelected(m_propHover) ) { - DoAddToSelection(m_propHover); + // Additional requirement is that the hovered property + // is adjacent to edges of selection. + const wxArrayPGProperty& selection = GetSelectedProperties(); + + // Since categories cannot be selected along with 'other' + // properties, exclude them from iterator flags. + int iterFlags = wxPG_ITERATE_VISIBLE & (~wxPG_PROP_CATEGORY); + + for ( int i=(selection.size()-1); i>=0; i-- ) + { + // TODO: This could be optimized by keeping track of + // which properties are at the edges of selection. + wxPGProperty* selProp = selection[i]; + if ( state->ArePropertiesAdjacent(m_propHover, selProp, + iterFlags) ) + { + DoAddToSelection(m_propHover); + break; + } + } } } return true; @@ -5148,14 +5232,25 @@ void wxPropertyGrid::AddActionTrigger( int action, int keycode, int modifiers ) 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 )