]> git.saurik.com Git - wxWidgets.git/blobdiff - src/propgrid/propgridiface.cpp
Update OpenVMS compile support
[wxWidgets.git] / src / propgrid / propgridiface.cpp
index 018616a32a0a3818ed6d1983eee908be8570dc47..f762133260cf0fa54bc596752e7063a57c67db6e 100644 (file)
@@ -4,7 +4,7 @@
 // Author:      Jaakko Salli
 // Modified by:
 // Created:     2008-08-24
-// RCS-ID:      $Id:
+// RCS-ID:      $Id$
 // Copyright:   (c) Jaakko Salli
 // Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
@@ -16,6 +16,8 @@
     #pragma hdrstop
 #endif
 
+#if wxUSE_PROPGRID
+
 #ifndef WX_PRECOMP
     #include "wx/defs.h"
     #include "wx/object.h"
     #include "wx/button.h"
     #include "wx/pen.h"
     #include "wx/brush.h"
-    #include "wx/cursor.h"
-    #include "wx/dialog.h"
     #include "wx/settings.h"
-    #include "wx/msgdlg.h"
-    #include "wx/choice.h"
-    #include "wx/stattext.h"
-    #include "wx/scrolwin.h"
-    #include "wx/dirdlg.h"
-    #include "wx/layout.h"
     #include "wx/sizer.h"
-    #include "wx/textdlg.h"
-    #include "wx/filedlg.h"
-    #include "wx/statusbr.h"
     #include "wx/intl.h"
-    #include "wx/frame.h"
 #endif
 
-#include <wx/propgrid/property.h>
-#include <wx/propgrid/propgrid.h>
-
-#include <typeinfo>
+#include "wx/propgrid/property.h"
+#include "wx/propgrid/propgrid.h"
 
 
 const wxChar *wxPGTypeName_long = wxT("long");
@@ -65,31 +53,56 @@ const wxChar *wxPGTypeName_wxArrayString = wxT("arrstring");
 // VariantDatas
 // ----------------------------------------------------------------------------
 
-WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataPoint, wxPoint)
-WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataSize, wxSize)
-WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataArrayInt, wxArrayInt)
-WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataLongLong, wxLongLong)
-WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataULongLong, wxULongLong)
-
-WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA(wxPGVariantDataFont, wxFont)
+WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxPoint, WXDLLIMPEXP_PROPGRID)
+WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxSize, WXDLLIMPEXP_PROPGRID)
+WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(wxArrayInt, WXDLLIMPEXP_PROPGRID)
 
-wxObject* wxPG_VariantToWxObject( const wxVariant& variant, wxClassInfo* classInfo )
+// For wxLongLong and wxULongLong have custom classname << variant
+// implementation for improved flexibility.
+WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(wxLongLong, WXDLLIMPEXP_PROPGRID)
+WX_PG_IMPLEMENT_VARIANT_DATA_EQ(wxLongLong, WXDLLIMPEXP_PROPGRID)
+WXDLLIMPEXP_PROPGRID wxLongLong& operator << ( wxLongLong &value, const wxVariant &variant )
 {
-    if ( !variant.IsValueKindOf(classInfo) )
-        return (wxObject*) NULL;
-
-    wxVariantData* vdata = variant.GetData();
-
-    wxPGVariantData* pgvdata = wxDynamicCastVariantData(vdata, wxPGVariantData);
-    if ( pgvdata )
-         return (wxObject*) pgvdata->GetValuePtr();
-
-    if ( wxPGIsVariantClassInfo(wxPGVariantDataGetClassInfo(vdata), wxobject) )
-        return variant.GetWxObjectPtr();
+    wxLongLong_t ll;
+    if ( !wxPGVariantToLongLong(variant, &ll) )
+    {
+        wxFAIL_MSG("Cannot convert to wxLongLong");
+    }
+    value = ll;
+    return value;
+}
+WXDLLIMPEXP_PROPGRID wxLongLong_t& operator << ( wxLongLong_t &value, const wxVariant &variant )
+{
+    if ( !wxPGVariantToLongLong(variant, &value) )
+    {
+        wxFAIL_MSG("Cannot convert to wxLongLong");
+    }
+    return value;
+}
 
-    return (wxObject*) NULL;
+WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_NO_EQ_NO_GETTER(wxULongLong, WXDLLIMPEXP_PROPGRID)
+WX_PG_IMPLEMENT_VARIANT_DATA_EQ(wxULongLong, WXDLLIMPEXP_PROPGRID)
+WXDLLIMPEXP_PROPGRID wxULongLong& operator << ( wxULongLong &value, const wxVariant &variant )
+{
+    wxULongLong_t ull;
+    if ( !wxPGVariantToULongLong(variant, &ull) )
+    {
+        wxFAIL_MSG("Cannot convert to wxULongLong");
+    }
+    value = ull;
+    return value;
+}
+WXDLLIMPEXP_PROPGRID wxULongLong_t& operator << ( wxULongLong_t &value, const wxVariant &variant )
+{
+    if ( !wxPGVariantToULongLong(variant, &value) )
+    {
+        wxFAIL_MSG("Cannot convert to wxULongLong");
+    }
+    return value;
 }
 
+IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxFont, WXDLLIMPEXP_PROPGRID)
+
 // -----------------------------------------------------------------------
 // wxVariant helpers
 // -----------------------------------------------------------------------
@@ -99,15 +112,16 @@ long wxPGVariantToInt( const wxVariant& variant, long defVal )
     if ( variant.IsNull() )
         return defVal;
 
-    if ( wxPGIsVariantType(variant, long) )
+    if ( variant.GetType() == wxS("long") )
         return variant.GetLong();
 
-    if ( wxPGIsVariantType(variant, bool) )
+    if ( variant.GetType() == wxS("bool") )
         return variant.GetBool() ? 1 : 0;
 
-    if ( typeid(*variant.GetData()) == typeid(wxPGVariantDataLongLong) )
+    if ( variant.GetType() == wxS("wxLongLong") )
     {
-        wxLongLong ll = ((const wxPGVariantDataLongLong&)variant).GetValue();
+        wxLongLong ll;
+        ll << variant;
         if ( ll >= LONG_MAX )
             return LONG_MAX;
         else if ( ll <= LONG_MIN )
@@ -117,7 +131,7 @@ long wxPGVariantToInt( const wxVariant& variant, long defVal )
 
     long l = defVal;
 
-    if ( wxPGIsVariantType(variant, string) )
+    if ( variant.GetType() == wxPG_VARIANT_TYPE_STRING )
         variant.GetString().ToLong(&l, 0);
 
     return l;
@@ -130,15 +144,18 @@ bool wxPGVariantToLongLong( const wxVariant& variant, wxLongLong_t* pResult )
     if ( variant.IsNull() )
         return false;
 
-    if ( wxPGIsVariantType(variant, long) )
+    wxString variantType = variant.GetType();
+
+    if ( variantType == wxPG_VARIANT_TYPE_LONG )
     {
         *pResult = variant.GetLong();
         return true;
     }
 
-    if ( typeid(*variant.GetData()) == typeid(wxPGVariantDataLongLong) )
+    if ( variantType == wxLongLong_VariantType )
     {
-        *pResult = ((const wxPGVariantDataLongLong&)variant).GetValue().GetValue();
+        // NOTE: << operator uses this functions, so we can't use it here
+        *pResult = wxLongLongRefFromVariant(variant).GetValue();
         return true;
     }
 
@@ -152,15 +169,18 @@ bool wxPGVariantToULongLong( const wxVariant& variant, wxULongLong_t* pResult )
     if ( variant.IsNull() )
         return false;
 
-    if ( wxPGIsVariantType(variant, long) )
+    wxString variantType = variant.GetType();
+
+    if ( variantType == wxPG_VARIANT_TYPE_LONG )
     {
         *pResult = (unsigned long)variant.GetLong();
         return true;
     }
 
-    if ( typeid(*variant.GetData()) == typeid(wxPGVariantDataULongLong) )
+    if ( variantType == wxULongLong_VariantType )
     {
-        *pResult = ((const wxPGVariantDataULongLong&)variant).GetValue().GetValue();
+        // NOTE: << operator uses this functions, so we can't use it here
+        *pResult = wxULongLongRefFromVariant(variant).GetValue();
         return true;
     }
 
@@ -174,26 +194,29 @@ bool wxPGVariantToDouble( const wxVariant& variant, double* pResult )
     if ( variant.IsNull() )
         return false;
 
-    if ( wxPGIsVariantType(variant, double) )
+    wxString variantType = variant.GetType();
+
+    if ( variantType == wxPG_VARIANT_TYPE_DOUBLE )
     {
         *pResult = variant.GetDouble();
         return true;
     }
 
-    if ( wxPGIsVariantType(variant, long) )
+    if ( variantType == wxPG_VARIANT_TYPE_LONG )
     {
         *pResult = (double)variant.GetLong();
         return true;
     }
 
-    if ( typeid(*variant.GetData()) == typeid(wxPGVariantDataLongLong) )
+    if ( variantType == wxLongLong_VariantType )
     {
-        wxLongLong ll = ((const wxPGVariantDataLongLong&)variant).GetValue();
+        wxLongLong ll;
+        ll << variant;
         *pResult = ll.ToDouble();
         return true;
     }
 
-    if ( wxPGIsVariantType(variant, string) )
+    if ( variantType == wxPG_VARIANT_TYPE_STRING )
         if ( variant.GetString().ToDouble(pResult) )
             return true;
 
@@ -201,38 +224,30 @@ bool wxPGVariantToDouble( const wxVariant& variant, double* pResult )
 }
 
 // -----------------------------------------------------------------------
-// Choice related methods
+// wxPGPropArgCls
 // -----------------------------------------------------------------------
 
-void wxPropertyGridInterface::AddPropertyChoice( wxPGPropArg id,
-                                                 const wxString& label,
-                                                 int value )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    p->InsertChoice(label,-1,value);
-}
-
-
-void wxPropertyGridInterface::InsertPropertyChoice( wxPGPropArg id,
-                                                    const wxString& label,
-                                                    int index,
-                                                    int value )
-{
-    wxPG_PROP_ARG_CALL_PROLOG()
-
-    p->InsertChoice(label,index,value);
-}
-
-
-void wxPropertyGridInterface::DeletePropertyChoice( wxPGPropArg id,
-                                                    int index )
+wxPGProperty* wxPGPropArgCls::GetPtr( wxPropertyGridInterface* iface ) const
 {
-    wxPG_PROP_ARG_CALL_PROLOG()
+    if ( m_flags == IsProperty )
+    {
+        wxASSERT_MSG( m_ptr.property, wxT("invalid property ptr") );
+        return m_ptr.property;
+    }
+    else if ( m_flags & IsWxString )
+        return iface->GetPropertyByNameA(*m_ptr.stringName);
+    else if ( m_flags & IsCharPtr )
+        return iface->GetPropertyByNameA(m_ptr.charName);
+#if wxUSE_WCHAR_T
+    else if ( m_flags & IsWCharPtr )
+        return iface->GetPropertyByNameA(m_ptr.wcharName);
+#endif
 
-    p->DeleteChoice(index);
+    return NULL;
 }
 
+// -----------------------------------------------------------------------
+// wxPropertyGridInterface
 // -----------------------------------------------------------------------
 
 void wxPropertyGridInterface::RefreshGrid( wxPropertyGridPageState* state )
@@ -275,7 +290,7 @@ wxPGProperty* wxPropertyGridInterface::AppendIn( wxPGPropArg id, wxPGProperty* n
 wxPGProperty* wxPropertyGridInterface::Insert( wxPGPropArg id, wxPGProperty* property )
 {
     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
-    wxPGProperty* retp = m_pState->DoInsert(p->GetParent(), p->GetArrIndex(), property);
+    wxPGProperty* retp = m_pState->DoInsert(p->GetParent(), p->GetIndexInParent(), property);
     RefreshGrid();
     return retp;
 }
@@ -299,16 +314,41 @@ void wxPropertyGridInterface::DeleteProperty( wxPGPropArg id )
     wxPropertyGridPageState* state = p->GetParentState();
     wxPropertyGrid* grid = state->GetGrid();
 
+    if ( grid->GetState() == state )
+        grid->DoSelectProperty(NULL, wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE);
+
+    state->DoDelete( p, true );
+
+    RefreshGrid(state);
+}
+
+// -----------------------------------------------------------------------
+
+wxPGProperty* wxPropertyGridInterface::RemoveProperty( wxPGPropArg id )
+{
+    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
+
+    wxCHECK( !p->GetChildCount() || p->HasFlag(wxPG_PROP_AGGREGATE),
+             wxNullProperty);
+
+    wxPropertyGridPageState* state = p->GetParentState();
+    wxPropertyGrid* grid = state->GetGrid();
+
     if ( grid->GetState() == state )
     {
-        bool selRes = grid->DoSelectProperty(NULL, wxPG_SEL_DELETING);
-        wxPG_CHECK_RET_DBG( selRes,
-                            wxT("failed to deselect a property (editor probably had invalid value)") );
+        grid->DoSelectProperty(NULL,
+            wxPG_SEL_DELETING|wxPG_SEL_NOVALIDATE);
     }
 
-    state->DoDelete( p );
+    state->DoDelete( p, false );
+
+    // Mark the property as 'unattached'
+    p->m_parentState = NULL;
+    p->m_parent = NULL;
 
     RefreshGrid(state);
+
+    return p;
 }
 
 // -----------------------------------------------------------------------
@@ -343,14 +383,23 @@ wxPGProperty* wxPropertyGridInterface::ReplaceProperty( wxPGPropArg id, wxPGProp
 // wxPropertyGridInterface property operations
 // -----------------------------------------------------------------------
 
-bool wxPropertyGridInterface::ClearSelection()
+bool wxPropertyGridInterface::ClearSelection( bool validation )
 {
+    int flags = 0;
+    if ( !validation )
+        flags |= wxPG_SEL_NOVALIDATE;
+
     wxPropertyGridPageState* state = m_pState;
-    wxPropertyGrid* pg = state->GetGrid();
-    if ( pg->GetState() == state )
-        return pg->DoClearSelection();
-    else
-        state->SetSelection(NULL);
+
+    if ( state )
+    {
+        wxPropertyGrid* pg = state->GetGrid();
+        if ( pg->GetState() == state )
+            return pg->DoSelectProperty(NULL, flags);
+        else
+            state->SetSelection(NULL);
+    }
+
     return true;
 }
 
@@ -413,8 +462,7 @@ bool wxPropertyGridInterface::ExpandAll( bool doExpand )
     if ( GetSelection() && GetSelection() != state->DoGetRoot() &&
          !doExpand )
     {
-        if ( !pg->ClearSelection() )
-            return false;
+        pg->ClearSelection(false);
     }
 
     wxPGVIterator it;
@@ -460,23 +508,41 @@ void wxPropertyGridInterface::SetPropertyValueUnspecified( wxPGPropArg id )
         p->GetParentState()->DoSetPropertyValueUnspecified(p);
 }
 
+// -----------------------------------------------------------------------
+
+void wxPropertyGridInterface::ClearModifiedStatus()
+{
+    unsigned int pageIndex = 0;
+
+    for (;;)
+    {
+        wxPropertyGridPageState* page = GetPageState(pageIndex);
+        if ( !page ) break;
+
+        page->DoGetRoot()->SetFlagRecursively(wxPG_PROP_MODIFIED, false);
+
+        pageIndex++;
+    }
+}
+
 // -----------------------------------------------------------------------
 // wxPropertyGridInterface property value setting and getting
 // -----------------------------------------------------------------------
 
-void wxPGGetFailed( const wxPGProperty* p, const wxChar* typestr )
+void wxPGGetFailed( const wxPGProperty* p, const wxString& typestr )
 {
-    wxPGTypeOperationFailed(p,typestr,wxT("Get"));
+    wxPGTypeOperationFailed(p, typestr, wxS("Get"));
 }
 
 // -----------------------------------------------------------------------
 
-void wxPGTypeOperationFailed( const wxPGProperty* p, const wxChar* typestr,
-    const wxChar* op )
+void wxPGTypeOperationFailed( const wxPGProperty* p,
+                              const wxString& typestr,
+                              const wxString& op )
 {
     wxASSERT( p != NULL );
     wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."),
-        op,p->GetLabel().c_str(),p->GetValue().GetType().c_str(),typestr );
+        op.c_str(), p->GetLabel().c_str(), p->GetValue().GetType().c_str(), typestr.c_str() );
 }
 
 // -----------------------------------------------------------------------
@@ -559,6 +625,24 @@ void wxPropertyGridInterface::DoSetPropertyAttribute( wxPGPropArg id, const wxSt
 
 // -----------------------------------------------------------------------
 
+void wxPropertyGridInterface::SetPropertyAttributeAll( const wxString& attrName,
+                                                       wxVariant value )
+{
+    unsigned int pageIndex = 0;
+
+    for (;;)
+    {
+        wxPropertyGridPageState* page = GetPageState(pageIndex);
+        if ( !page ) break;
+
+        DoSetPropertyAttribute(page->DoGetRoot(), attrName, value, wxPG_RECURSE);
+
+        pageIndex++;
+    }
+}
+
+// -----------------------------------------------------------------------
+
 void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty* targetArr,
                                                      wxPGProperty::FlagType flags,
                                                      bool inverse,
@@ -588,34 +672,6 @@ void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty* targetAr
 
 // -----------------------------------------------------------------------
 
-void wxPropertyGridInterface::SetPropertiesFlag( const wxArrayPGProperty& srcArr,
-                                                 wxPGProperty::FlagType flags,
-                                                 bool inverse )
-{
-    unsigned int i;
-
-    for ( i=0; i<srcArr.size(); i++ )
-    {
-        wxPGProperty* property = srcArr[i];
-
-        if ( !inverse )
-            property->SetFlag(flags);
-        else
-            property->ClearFlag(flags);
-    }
-
-    // If collapsed flag or hidden was manipulated, we need to update virtual
-    // size.
-    wxPropertyGrid* pg = GetPropertyGrid();
-    if ( flags & (wxPG_PROP_COLLAPSED|wxPG_PROP_HIDDEN) )
-    {
-        GetState()->VirtualHeightChanged();
-        pg->RecalculateVirtualSize();
-    }
-}
-
-// -----------------------------------------------------------------------
-
 void wxPropertyGridInterface::SetBoolChoices( const wxString& trueChoice,
                                                  const wxString& falseChoice )
 {
@@ -625,25 +681,6 @@ void wxPropertyGridInterface::SetBoolChoices( const wxString& trueChoice,
 
 // -----------------------------------------------------------------------
 
-wxPGChoices gs_emptyChoices;
-
-wxPGChoices& wxPropertyGridInterface::GetPropertyChoices( wxPGPropArg id )
-{
-    wxPG_PROP_ARG_CALL_PROLOG_RETVAL(gs_emptyChoices)
-
-    wxPGChoiceInfo ci;
-    ci.m_choices = (wxPGChoices*) NULL;
-
-    p->GetChoiceInfo(&ci);
-
-    if ( !ci.m_choices )
-        return gs_emptyChoices;
-
-    return *ci.m_choices;
-}
-
-// -----------------------------------------------------------------------
-
 wxPGProperty* wxPropertyGridInterface::DoGetPropertyByName( const wxString& name ) const
 {
     return m_pState->BaseGetPropertyByName(name);
@@ -768,6 +805,60 @@ bool wxPropertyGridInterface::SetPropertyMaxLength( wxPGPropArg id, int maxLen )
     return true;
 }
 
+// -----------------------------------------------------------------------
+
+void
+wxPropertyGridInterface::SetPropertyBackgroundColour( wxPGPropArg id,
+                                                      const wxColour& colour,
+                                                      bool recursively )
+{
+    wxPG_PROP_ARG_CALL_PROLOG()
+    p->SetBackgroundColour( colour, recursively );
+    RefreshProperty( p );
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGridInterface::SetPropertyTextColour( wxPGPropArg id,
+                                                     const wxColour& colour,
+                                                     bool recursively )
+{
+    wxPG_PROP_ARG_CALL_PROLOG()
+    p->SetTextColour( colour, recursively );
+    RefreshProperty( p );
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGridInterface::SetPropertyColoursToDefault( wxPGPropArg id )
+{
+    wxPG_PROP_ARG_CALL_PROLOG()
+
+    p->m_cells.clear();
+}
+
+// -----------------------------------------------------------------------
+
+void wxPropertyGridInterface::SetPropertyCell( wxPGPropArg id,
+                                               int column,
+                                               const wxString& text,
+                                               const wxBitmap& bitmap,
+                                               const wxColour& fgCol,
+                                               const wxColour& bgCol )
+{
+    wxPG_PROP_ARG_CALL_PROLOG()
+
+    wxPGCell& cell = p->GetCell(column);
+    if ( text.length() && text != wxPG_LABEL )
+        cell.SetText(text);
+    if ( bitmap.IsOk() )
+        cell.SetBitmap(bitmap);
+    if ( fgCol != wxNullColour )
+        cell.SetFgCol(fgCol);
+    if ( bgCol != wxNullColour )
+        cell.SetBgCol(bgCol);
+}
+
 // -----------------------------------------------------------------------
 // GetPropertyValueAsXXX methods
 
@@ -809,30 +900,6 @@ bool wxPropertyGridInterface::GetPropertyValueAsBool( wxPGPropArg id ) const
 
 IMPLEMENT_GET_VALUE(long,long,Long,0)
 IMPLEMENT_GET_VALUE(double,double,Double,0.0)
-IMPLEMENT_GET_VALUE(void,void*,VoidPtr,NULL)
-
-// wxObject is different than others.
-wxObject* wxPropertyGridInterface::GetPropertyValueAsWxObjectPtr( wxPGPropArg id ) const
-{
-    wxPG_PROP_ARG_CALL_PROLOG_RETVAL((wxObject*)NULL)
-
-    wxVariant value = p->GetValue();
-    wxVariantData* vdata = value.GetData();
-
-    if ( !vdata->GetValueClassInfo() )
-        return (wxObject*) NULL;
-
-       wxPGVariantData* pgvdata = wxDynamicCastVariantData(vdata, wxPGVariantData);
-    if ( pgvdata )
-         return (wxObject*) pgvdata->GetValuePtr();
-
-    if ( wxPGIsVariantClassInfo(wxPGVariantDataGetClassInfo(vdata), wxobject) )
-        return (wxObject*) value.GetWxObjectPtr();
-
-    return (wxObject*) NULL;
-}
-
-// -----------------------------------------------------------------------
 
 bool wxPropertyGridInterface::IsPropertyExpanded( wxPGPropArg id ) const
 {
@@ -926,14 +993,17 @@ wxString wxPropertyGridInterface::SaveEditableState( int includedStates ) const
 
     //
     // Save state on page basis
-    size_t pageIndex = 0;
-    wxPropertyGridPageState* pageState = GetPageState(pageIndex);
+    unsigned int pageIndex = 0;
     wxArrayPtrVoid pageStates;
-    while ( pageState )
+
+    for (;;)
     {
-        pageStates.Add(pageState);
-        pageIndex += 1;
-        pageState = GetPageState(pageIndex);
+        wxPropertyGridPageState* page = GetPageState(pageIndex);
+        if ( !page ) break;
+
+        pageStates.Add(page);
+
+        pageIndex++;
     }
 
     for ( pageIndex=0; pageIndex < pageStates.size(); pageIndex++ )
@@ -967,7 +1037,7 @@ wxString wxPropertyGridInterface::SaveEditableState( int includedStates ) const
 
                 if ( !p->HasFlag(wxPG_PROP_COLLAPSED) )
                     result += EscapeDelimiters(p->GetName());
-                    result += wxS(",");
+                result += wxS(",");
 
             }
 
@@ -1001,6 +1071,12 @@ wxString wxPropertyGridInterface::SaveEditableState( int includedStates ) const
             else
                 result += wxS("0;");
         }
+        if ( includedStates & DescBoxState )
+        {
+            wxVariant v = GetEditableStateItem(wxS("descboxheight"));
+            if ( !v.IsNull() )
+                result += wxString::Format(wxS("descboxheight=%i;"), (int)v.GetLong());
+        }
         result.RemoveLast();  // Remove last semicolon
         result += wxS("|");
     }
@@ -1138,6 +1214,21 @@ bool wxPropertyGridInterface::RestoreEditableState( const wxString& src, int res
                         }
                     }
                 }
+                else if ( key == wxS("descboxheight") )
+                {
+                    if ( restoreStates & DescBoxState )
+                    {
+                        long descBoxHeight;
+                        if ( values.size() == 1 && values[0].ToLong(&descBoxHeight) )
+                        {
+                            SetEditableStateItem(wxS("descboxheight"), descBoxHeight);
+                        }
+                        else
+                        {
+                            res = false;
+                        }
+                    }
+                }
                 else
                 {
                     res = false;
@@ -1183,3 +1274,5 @@ bool wxPropertyGridInterface::RestoreEditableState( const wxString& src, int res
     return res;
 }
 
+#endif  // wxUSE_PROPGRID
+