X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/94b8ecf1cdefea63f07f9ed2b54a2ad2556ec001..b80fdc029995a0c2ce04910e26d652292c64d7bc:/src/propgrid/propgridpagestate.cpp diff --git a/src/propgrid/propgridpagestate.cpp b/src/propgrid/propgridpagestate.cpp index 59c3a88a39..b1dd806885 100644 --- a/src/propgrid/propgridpagestate.cpp +++ b/src/propgrid/propgridpagestate.cpp @@ -107,7 +107,8 @@ void wxPropertyGridIteratorBase::Assign( const wxPropertyGridIteratorBase& it ) void wxPropertyGridIteratorBase::Prev() { wxPGProperty* property = m_property; - wxASSERT( property ); + if ( !property ) + return; wxPGProperty* parent = property->GetParent(); wxASSERT( parent ); @@ -152,7 +153,8 @@ void wxPropertyGridIteratorBase::Prev() void wxPropertyGridIteratorBase::Next( bool iterateChildren ) { wxPGProperty* property = m_property; - wxASSERT( property ); + if ( !property ) + return; if ( property->GetChildCount() && wxPG_ITERATOR_PARENTEXMASK_TEST(property, m_parentExMask) && @@ -206,7 +208,6 @@ wxPropertyGridPageState::wxPropertyGridPageState() m_properties = &m_regularArray; m_abcArray = NULL; m_currentCategory = NULL; - m_selected = NULL; m_width = 0; m_virtualHeight = 0; m_lastCaptionBottomnest = 1; @@ -216,6 +217,9 @@ wxPropertyGridPageState::wxPropertyGridPageState() m_colWidths.push_back( wxPG_DEFAULT_SPLITTERX ); m_colWidths.push_back( wxPG_DEFAULT_SPLITTERX ); m_fSplitterX = wxPG_DEFAULT_SPLITTERX; + + // By default, we only have the 'value' column editable + m_editableColumns.push_back(1); } // ----------------------------------------------------------------------- @@ -255,7 +259,7 @@ void wxPropertyGridPageState::InitNonCatMode() wxPGProperty* parent = p->GetParent(); if ( parent->IsCategory() || parent->IsRoot() ) { - m_abcArray->AddChild2(p); + m_abcArray->DoAddChild(p); p->m_parent = &m_regularArray; } } @@ -268,6 +272,15 @@ void wxPropertyGridPageState::InitNonCatMode() void wxPropertyGridPageState::DoClear() { + if ( m_pPropGrid && m_pPropGrid->GetState() == this ) + { + m_pPropGrid->ClearSelection(false); + } + else + { + m_selection.clear(); + } + m_regularArray.Empty(); if ( m_abcArray ) m_abcArray->Empty(); @@ -280,8 +293,6 @@ void wxPropertyGridPageState::DoClear() m_virtualHeight = 0; m_vhCalcPending = 0; - - m_selected = NULL; } // ----------------------------------------------------------------------- @@ -346,9 +357,9 @@ void wxPropertyGridPageState::OnClientWidthChange( int newWidth, int widthChange long timeSinceCreation = (::wxGetLocalTimeMillis() - GetGrid()->m_timeCreated).ToLong(); // If too long, don't set splitter - if ( timeSinceCreation < 3000 ) + if ( timeSinceCreation < 250 ) { - if ( m_properties->GetChildCount() || timeSinceCreation > 750 ) + if ( m_properties->GetChildCount() ) { SetSplitterLeft( false ); } @@ -599,23 +610,6 @@ bool wxPropertyGridPageState::EnableCategories( bool enable ) // ----------------------------------------------------------------------- -#if wxUSE_STL -#include - -static bool wxPG_SortFunc_ByFunction(wxPGProperty *p1, wxPGProperty *p2) -{ - wxPropertyGrid* pg = p1->GetGrid(); - wxPGSortCallback sortFunction = pg->GetSortFunction(); - return sortFunction(pg, p1, p2) < 0; -} - -static bool wxPG_SortFunc_ByLabel(wxPGProperty *p1, wxPGProperty *p2) -{ - return p1->GetLabel().CmpNoCase( p2->GetLabel() ) < 0; -} - -#else - static int wxPG_SortFunc_ByFunction(wxPGProperty **pp1, wxPGProperty **pp2) { wxPGProperty *p1 = *pp1; @@ -632,6 +626,24 @@ static int wxPG_SortFunc_ByLabel(wxPGProperty **pp1, wxPGProperty **pp2) return p1->GetLabel().CmpNoCase( p2->GetLabel() ); } +#if 0 +// +// For wxVector w/ wxUSE_STL=1, you would use code like this instead: +// + +#include + +static bool wxPG_SortFunc_ByFunction(wxPGProperty *p1, wxPGProperty *p2) +{ + wxPropertyGrid* pg = p1->GetGrid(); + wxPGSortCallback sortFunction = pg->GetSortFunction(); + return sortFunction(pg, p1, p2) < 0; +} + +static bool wxPG_SortFunc_ByLabel(wxPGProperty *p1, wxPGProperty *p2) +{ + return p1->GetLabel().CmpNoCase( p2->GetLabel() ) < 0; +} #endif void wxPropertyGridPageState::DoSortChildren( wxPGProperty* p, @@ -652,18 +664,21 @@ void wxPropertyGridPageState::DoSortChildren( wxPGProperty* p, && !p->IsCategory() && !p->IsRoot() ) return; -#if wxUSE_STL + if ( GetGrid()->GetSortFunction() ) + p->m_children.Sort( wxPG_SortFunc_ByFunction ); + else + p->m_children.Sort( wxPG_SortFunc_ByLabel ); + +#if 0 + // + // For wxVector w/ wxUSE_STL=1, you would use code like this instead: + // if ( GetGrid()->GetSortFunction() ) std::sort(p->m_children.begin(), p->m_children.end(), wxPG_SortFunc_ByFunction); else std::sort(p->m_children.begin(), p->m_children.end(), wxPG_SortFunc_ByLabel); -#else - if ( GetGrid()->GetSortFunction() ) - p->m_children.Sort( wxPG_SortFunc_ByFunction ); - else - p->m_children.Sort( wxPG_SortFunc_ByLabel ); #endif // Fix indices @@ -720,11 +735,13 @@ wxPGProperty* wxPropertyGridPageState::DoGetItemAtY( int y ) const // ----------------------------------------------------------------------- -wxPropertyGridHitTestResult wxPropertyGridPageState::HitTest( const wxPoint&pt ) const +wxPropertyGridHitTestResult +wxPropertyGridPageState::HitTest( const wxPoint&pt ) const { wxPropertyGridHitTestResult result; - result.column = HitTestH( pt.x, &result.splitter, &result.splitterHitOffset ); - result.property = DoGetItemAtY( pt.y ); + result.m_column = HitTestH( pt.x, &result.m_splitter, + &result.m_splitterHitOffset ); + result.m_property = DoGetItemAtY( pt.y ); return result; } @@ -753,8 +770,10 @@ int wxPropertyGridPageState::GetColumnFitWidth(wxClientDC& dc, if ( col == 0 ) w += ( ((int)p->m_depth-1) * pg->m_subgroup_extramargin ); - // - // TODO: Add bitmap support. + // account for the bitmap + if ( col == 1 ) + w += p->GetImageOffset(pg->GetImageRect(p, -1).GetWidth()); + w += (wxPG_XBEFORETEXT*2); @@ -863,7 +882,7 @@ void wxPropertyGridPageState::SetSplitterLeft( bool subProps ) { wxPropertyGrid* pg = GetGrid(); wxClientDC dc(pg); - dc.SetFont(pg->m_font); + dc.SetFont(pg->GetFont()); int maxW = GetColumnFitWidth(dc, m_properties, 0, subProps); @@ -880,7 +899,7 @@ wxSize wxPropertyGridPageState::DoFitColumns( bool WXUNUSED(allowGridResize) ) { wxPropertyGrid* pg = GetGrid(); wxClientDC dc(pg); - dc.SetFont(pg->m_font); + dc.SetFont(pg->GetFont()); int marginWidth = pg->m_marginWidth; int accWid = marginWidth; @@ -929,10 +948,6 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) wxPropertyGrid* pg = GetGrid(); -#ifdef __WXDEBUG__ - const bool debug = false; -#endif - unsigned int i; unsigned int lastColumn = m_colWidths.size() - 1; int width = m_width; @@ -940,14 +955,11 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) // // Column to reduce, if needed. Take last one that exceeds minimum width. - // Except if auto splitter centering is used, in which case use widest. int reduceCol = -1; - int highestColWidth = 0; -#ifdef __WXDEBUG__ - if ( debug ) - wxLogDebug(wxT("ColumnWidthCheck (virtualWidth: %i, clientWidth: %i)"), width, clientWidth); -#endif + wxLogTrace("propgrid", + wxS("ColumnWidthCheck (virtualWidth: %i, clientWidth: %i)"), + width, clientWidth); // // Check min sizes @@ -960,18 +972,9 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) } else { - if ( pg->HasFlag(wxPG_SPLITTER_AUTO_CENTER) ) - { - if ( m_colWidths[i] >= highestColWidth ) - { - highestColWidth = m_colWidths[i]; - reduceCol = i; - } - } - else - { - reduceCol = i; - } + // Always reduce the last column that is larger than minimum size + // (looks nicer, even with auto-centering enabled). + reduceCol = i; } } @@ -979,10 +982,9 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) for ( i=0; iHasVirtualWidth(),colsWidth); -#endif + wxLogTrace("propgrid", + wxS(" HasVirtualWidth: %i colsWidth: %i"), + (int)pg->HasVirtualWidth(), colsWidth); // Then mode-based requirement if ( !pg->HasVirtualWidth() ) @@ -993,10 +995,9 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) if ( colsWidth < width ) { // Increase column -#ifdef __WXDEBUG__ - if ( debug ) - wxLogDebug(wxT(" Adjust last column to %i"), m_colWidths[lastColumn] + widthHigher); -#endif + wxLogTrace("propgrid", + wxS(" Adjust last column to %i"), + m_colWidths[lastColumn] + widthHigher); m_colWidths[lastColumn] = m_colWidths[lastColumn] + widthHigher; } else if ( colsWidth > width ) @@ -1004,10 +1005,10 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) // Reduce column if ( reduceCol != -1 ) { - #ifdef __WXDEBUG__ - if ( debug ) - wxLogDebug(wxT(" Reduce column %i (by %i)"), reduceCol, -widthHigher); - #endif + wxLogTrace("propgrid", + wxT(" Reduce column %i (by %i)"), + reduceCol, -widthHigher); + // Reduce widest column, and recheck m_colWidths[reduceCol] = m_colWidths[reduceCol] + widthHigher; CheckColumnWidths(); @@ -1029,11 +1030,10 @@ void wxPropertyGridPageState::CheckColumnWidths( int widthChange ) pg->RecalculateVirtualSize(); } -#ifdef __WXDEBUG__ - if ( debug ) - for ( i=0; iGetInternalFlags() & wxPG_FL_DONT_CENTER_SPLITTER) && @@ -1141,6 +1141,29 @@ int wxPropertyGridPageState::HitTestH( int x, int* pSplitterHit, int* pSplitterH return col; } +bool wxPropertyGridPageState::ArePropertiesAdjacent( wxPGProperty* prop1, + wxPGProperty* prop2, + int iterFlags ) const +{ + const wxPGProperty* ap1 = + wxPropertyGridConstIterator::OneStep(this, + iterFlags, + prop1, + 1); + if ( ap1 && ap1 == prop2 ) + return true; + + const wxPGProperty* ap2 = + wxPropertyGridConstIterator::OneStep(this, + iterFlags, + prop1, + -1); + if ( ap2 && ap2 == prop2 ) + return true; + + return false; +} + // ----------------------------------------------------------------------- // wxPropertyGridPageState property value setting and getting // ----------------------------------------------------------------------- @@ -1162,7 +1185,8 @@ bool wxPropertyGridPageState::DoSetPropertyValueString( wxPGProperty* p, const w if ( res ) { p->SetValue(variant); - if ( m_selected==p && this==m_pPropGrid->GetState() ) + if ( p == m_pPropGrid->GetSelection() && + this == m_pPropGrid->GetState() ) m_pPropGrid->RefreshEditor(); } @@ -1178,7 +1202,8 @@ bool wxPropertyGridPageState::DoSetPropertyValue( wxPGProperty* p, wxVariant& va if ( p ) { p->SetValue(value); - if ( m_selected==p && this==m_pPropGrid->GetState() ) + if ( p == m_pPropGrid->GetSelection() && + this == m_pPropGrid->GetState() ) m_pPropGrid->RefreshEditor(); return true; @@ -1204,6 +1229,59 @@ bool wxPropertyGridPageState::DoSetPropertyValueWxObjectPtr( wxPGProperty* p, wx // wxPropertyGridPageState property operations // ----------------------------------------------------------------------- +bool wxPropertyGridPageState::DoIsPropertySelected( wxPGProperty* prop ) const +{ + const wxArrayPGProperty& selection = m_selection; + + for ( unsigned int i=0; iGetState() == this ) + { + // If first item (ie. one with the active editor) was + // deselected, then we need to take some extra measures. + wxArrayPGProperty sel = m_selection; + sel.erase( sel.begin() + i ); + + wxPGProperty* newFirst; + if ( sel.size() ) + newFirst = sel[0]; + else + newFirst = NULL; + + pg->DoSelectProperty(newFirst, + wxPG_SEL_DONT_SEND_EVENT); + + m_selection = sel; + + pg->Refresh(); + } + else + { + m_selection.erase( m_selection.begin() + i ); + } + return; + } + } +} + +// ----------------------------------------------------------------------- + bool wxPropertyGridPageState::DoCollapse( wxPGProperty* p ) { wxCHECK_MSG( p, false, wxT("invalid property id") ); @@ -1243,7 +1321,7 @@ bool wxPropertyGridPageState::DoSelectProperty( wxPGProperty* p, unsigned int fl if ( this == m_pPropGrid->GetState() ) return m_pPropGrid->DoSelectProperty( p, flags ); - m_selected = p; + DoSetSelection(p); return true; } @@ -1428,13 +1506,12 @@ void wxPropertyGridPageState::DoSetPropertyValues( const wxVariantList& list, wx } else { - #ifdef __WXDEBUG__ - if ( wxStrcmp(current->GetType(), p->GetValue().GetType()) != 0) - { - wxLogDebug(wxT("wxPropertyGridPageState::DoSetPropertyValues Warning: Setting value of property \"%s\" from variant"), - p->GetName().c_str()); - } - #endif + wxASSERT_LEVEL_2_MSG( + wxStrcmp(current->GetType(), p->GetValue().GetType()) == 0, + wxString::Format( + wxS("setting value of property \"%s\" from variant"), + p->GetName().c_str()) + ); p->SetValue(*current); } @@ -1570,16 +1647,18 @@ bool wxPropertyGridPageState::PrepareToAddItem( wxPGProperty* property, } } -#ifdef __WXDEBUG__ +#if wxDEBUG_LEVEL // Warn for identical names in debug mode. if ( BaseGetPropertyByName(property->GetName()) && (!scheduledParent || scheduledParent->IsCategory()) ) { - wxLogError(wxT("wxPropertyGrid: Warning - item with name \"%s\" already exists."), - property->GetName().c_str()); + wxFAIL_MSG(wxString::Format( + "wxPropertyGrid item with name \"%s\" already exists", + property->GetName())); + wxPGGlobalVars->m_warnings++; } -#endif +#endif // wxDEBUG_LEVEL // Make sure nothing is selected. if ( propGrid ) @@ -1659,11 +1738,11 @@ wxPGProperty* wxPropertyGridPageState::DoInsert( wxPGProperty* parent, int index if ( m_abcArray && !property->IsCategory() && (parentIsCategory || parentIsRoot) ) { - m_abcArray->AddChild2( property, -1, false ); + m_abcArray->DoAddChild( property, -1, false ); } // Add to current mode. - parent->AddChild2( property, index, true ); + parent->DoAddChild( property, index, true ); } else { @@ -1671,14 +1750,14 @@ wxPGProperty* wxPropertyGridPageState::DoInsert( wxPGProperty* parent, int index if ( parentIsCategory ) // Parent is category. - parent->AddChild2( property, index, false ); + parent->DoAddChild( property, index, false ); else if ( parentIsRoot ) // Parent is root. - m_regularArray.AddChild2( property, -1, false ); + m_regularArray.DoAddChild( property, -1, false ); // Add to current mode if ( !property->IsCategory() ) - m_abcArray->AddChild2( property, index, true ); + m_abcArray->DoAddChild( property, index, true ); } // category stuff @@ -1722,6 +1801,25 @@ void wxPropertyGridPageState::DoDelete( wxPGProperty* item, bool doDelete ) wxCHECK_RET( !parent->HasFlag(wxPG_PROP_AGGREGATE), wxT("wxPropertyGrid: Do not attempt to remove sub-properties.") ); + wxASSERT( item->GetParentState() == this ); + + wxPropertyGrid* pg = GetGrid(); + + if ( DoIsPropertySelected(item) ) + { + if ( pg && pg->GetState() == this ) + { + pg->DoRemoveFromSelection(item, + wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE); + } + else + { + DoRemoveFromSelection(item); + } + } + + item->SetFlag(wxPG_PROP_BEING_DELETED); + // Delete children if ( item->GetChildCount() && !item->HasFlag(wxPG_PROP_AGGREGATE) ) { @@ -1787,10 +1885,14 @@ void wxPropertyGridPageState::DoDelete( wxPGProperty* item, bool doDelete ) } } - if ( item->GetBaseName().length() && + if ( item->GetBaseName().length() && (parent->IsCategory() || parent->IsRoot()) ) m_dictName.erase(item->GetBaseName()); + // We need to clear parent grid's m_propHover, if it matches item + if ( pg && pg->m_propHover == item ) + pg->m_propHover = NULL; + // We can actually delete it now if ( doDelete ) delete item;