1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/propgrid/propgridiface.cpp 
   3 // Purpose:     wxPropertyGridInterface class 
   4 // Author:      Jaakko Salli 
   8 // Copyright:   (c) Jaakko Salli 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx/wx.h". 
  13 #include "wx/wxprec.h" 
  23     #include "wx/object.h" 
  25     #include "wx/string.h" 
  28     #include "wx/window.h" 
  31     #include "wx/dcmemory.h" 
  32     #include "wx/button.h" 
  35     #include "wx/settings.h" 
  40 #include "wx/propgrid/property.h" 
  41 #include "wx/propgrid/propgrid.h" 
  44 const wxChar 
*wxPGTypeName_long 
= wxT("long"); 
  45 const wxChar 
*wxPGTypeName_bool 
= wxT("bool"); 
  46 const wxChar 
*wxPGTypeName_double 
= wxT("double"); 
  47 const wxChar 
*wxPGTypeName_wxString 
= wxT("string"); 
  48 const wxChar 
*wxPGTypeName_void 
= wxT("void*"); 
  49 const wxChar 
*wxPGTypeName_wxArrayString 
= wxT("arrstring"); 
  52 // ---------------------------------------------------------------------------- 
  54 // ---------------------------------------------------------------------------- 
  56 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxPoint
, WXDLLIMPEXP_PROPGRID
) 
  57 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxSize
, WXDLLIMPEXP_PROPGRID
) 
  58 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(wxArrayInt
, WXDLLIMPEXP_PROPGRID
) 
  59 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxFont
, WXDLLIMPEXP_PROPGRID
) 
  61 // ----------------------------------------------------------------------- 
  63 // ----------------------------------------------------------------------- 
  65 wxPGProperty
* wxPGPropArgCls::GetPtr( wxPropertyGridInterface
* iface 
) const 
  67     if ( m_flags 
== IsProperty 
) 
  69         wxASSERT_MSG( m_ptr
.property
, wxT("invalid property ptr") ); 
  70         return m_ptr
.property
; 
  72     else if ( m_flags 
& IsWxString 
) 
  73         return iface
->GetPropertyByNameA(*m_ptr
.stringName
); 
  74     else if ( m_flags 
& IsCharPtr 
) 
  75         return iface
->GetPropertyByNameA(m_ptr
.charName
); 
  77     else if ( m_flags 
& IsWCharPtr 
) 
  78         return iface
->GetPropertyByNameA(m_ptr
.wcharName
); 
  84 // ----------------------------------------------------------------------- 
  85 // wxPropertyGridInterface 
  86 // ----------------------------------------------------------------------- 
  88 void wxPropertyGridInterface::RefreshGrid( wxPropertyGridPageState
* state 
) 
  93     wxPropertyGrid
* grid 
= state
->GetGrid(); 
  94     if ( grid
->GetState() == state 
&& !grid
->IsFrozen() ) 
 100 // ----------------------------------------------------------------------- 
 102 wxPGProperty
* wxPropertyGridInterface::Append( wxPGProperty
* property 
) 
 104     wxPGProperty
* retp 
= m_pState
->DoAppend(property
); 
 106     wxPropertyGrid
* grid 
= m_pState
->GetGrid(); 
 113 // ----------------------------------------------------------------------- 
 115 wxPGProperty
* wxPropertyGridInterface::AppendIn( wxPGPropArg id
, wxPGProperty
* newproperty 
) 
 117     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
) 
 118     wxPGProperty
* pwc 
= (wxPGProperty
*) p
; 
 119     wxPGProperty
* retp 
= m_pState
->DoInsert(pwc
, pwc
->GetChildCount(), newproperty
); 
 123 // ----------------------------------------------------------------------- 
 125 wxPGProperty
* wxPropertyGridInterface::Insert( wxPGPropArg id
, wxPGProperty
* property 
) 
 127     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
) 
 128     wxPGProperty
* retp 
= m_pState
->DoInsert(p
->GetParent(), p
->GetIndexInParent(), property
); 
 133 // ----------------------------------------------------------------------- 
 135 wxPGProperty
* wxPropertyGridInterface::Insert( wxPGPropArg id
, int index
, wxPGProperty
* newproperty 
) 
 137     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
) 
 138     wxPGProperty
* retp 
= m_pState
->DoInsert((wxPGProperty
*)p
,index
,newproperty
); 
 143 // ----------------------------------------------------------------------- 
 145 void wxPropertyGridInterface::DeleteProperty( wxPGPropArg id 
) 
 147     wxPG_PROP_ARG_CALL_PROLOG() 
 149     wxPropertyGridPageState
* state 
= p
->GetParentState(); 
 151     state
->DoDelete( p
, true ); 
 156 // ----------------------------------------------------------------------- 
 158 wxPGProperty
* wxPropertyGridInterface::RemoveProperty( wxPGPropArg id 
) 
 160     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
) 
 162     wxCHECK( !p
->GetChildCount() || p
->HasFlag(wxPG_PROP_AGGREGATE
), 
 165     wxPropertyGridPageState
* state 
= p
->GetParentState(); 
 167     state
->DoDelete( p
, false ); 
 174 // ----------------------------------------------------------------------- 
 176 wxPGProperty
* wxPropertyGridInterface::ReplaceProperty( wxPGPropArg id
, wxPGProperty
* property 
) 
 178     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
) 
 180     wxPGProperty
* replaced 
= p
; 
 181     wxCHECK_MSG( replaced 
&& property
, 
 183                  wxT("NULL property") ); 
 184     wxCHECK_MSG( !replaced
->IsCategory(), 
 186                  wxT("cannot replace this type of property") ); 
 187     wxCHECK_MSG( !m_pState
->IsInNonCatMode(), 
 189                  wxT("cannot replace properties in alphabetic mode") ); 
 191     // Get address to the slot 
 192     wxPGProperty
* parent 
= replaced
->GetParent(); 
 193     int ind 
= replaced
->GetIndexInParent(); 
 195     wxPropertyGridPageState
* state 
= replaced
->GetParentState(); 
 196     DeleteProperty(replaced
); // Must use generic Delete 
 197     state
->DoInsert(parent
,ind
,property
); 
 202 // ----------------------------------------------------------------------- 
 203 // wxPropertyGridInterface property operations 
 204 // ----------------------------------------------------------------------- 
 206 wxPGProperty
* wxPropertyGridInterface::GetSelection() const 
 208     return m_pState
->GetSelection(); 
 211 // ----------------------------------------------------------------------- 
 213 bool wxPropertyGridInterface::ClearSelection( bool validation 
) 
 215     bool res 
= DoClearSelection(validation
, wxPG_SEL_DONT_SEND_EVENT
); 
 216     wxPropertyGrid
* pg 
= GetPropertyGrid(); 
 222 // ----------------------------------------------------------------------- 
 224 bool wxPropertyGridInterface::DoClearSelection( bool validation
, 
 228         selFlags 
|= wxPG_SEL_NOVALIDATE
; 
 230     wxPropertyGridPageState
* state 
= m_pState
; 
 234         wxPropertyGrid
* pg 
= state
->GetGrid(); 
 235         if ( pg
->GetState() == state 
) 
 236             return pg
->DoSelectProperty(NULL
, selFlags
); 
 238             state
->DoSetSelection(NULL
); 
 244 // ----------------------------------------------------------------------- 
 246 void wxPropertyGridInterface::LimitPropertyEditing( wxPGPropArg id
, bool limit 
) 
 248     wxPG_PROP_ARG_CALL_PROLOG() 
 250     m_pState
->DoLimitPropertyEditing(p
, limit
); 
 254 // ----------------------------------------------------------------------- 
 256 bool wxPropertyGridInterface::EnableProperty( wxPGPropArg id
, bool enable 
) 
 258     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 260     wxPropertyGridPageState
* state 
= p
->GetParentState(); 
 261     wxPropertyGrid
* grid 
= state
->GetGrid(); 
 265         if ( !(p
->m_flags 
& wxPG_PROP_DISABLED
) ) 
 268         // If active, Set active Editor. 
 269         if ( grid 
&& grid
->GetState() == state 
&& p 
== grid
->GetSelection() ) 
 270             grid
->DoSelectProperty( p
, wxPG_SEL_FORCE 
); 
 274         if ( p
->m_flags 
& wxPG_PROP_DISABLED 
) 
 277         // If active, Disable as active Editor. 
 278         if ( grid 
&& grid
->GetState() == state 
&& p 
== grid
->GetSelection() ) 
 279             grid
->DoSelectProperty( p
, wxPG_SEL_FORCE 
); 
 282     state
->DoEnableProperty(p
, enable
); 
 284     RefreshProperty( p 
); 
 289 // ----------------------------------------------------------------------- 
 291 bool wxPropertyGridInterface::ExpandAll( bool doExpand 
) 
 293     wxPropertyGridPageState
* state 
= m_pState
; 
 295     if ( !state
->DoGetRoot()->GetChildCount() ) 
 298     wxPropertyGrid
* pg 
= state
->GetGrid(); 
 300     if ( GetSelection() && GetSelection() != state
->DoGetRoot() && 
 303         pg
->DoClearSelection(); 
 308     for ( it 
= GetVIterator( wxPG_ITERATE_ALL 
); !it
.AtEnd(); it
.Next() ) 
 310         wxPGProperty
* p 
= (wxPGProperty
*) it
.GetProperty(); 
 311         if ( p
->GetChildCount() ) 
 315                 if ( !p
->IsExpanded() ) 
 322                 if ( p
->IsExpanded() ) 
 324                     state
->DoCollapse(p
); 
 330     pg
->RecalculateVirtualSize(); 
 337 // ----------------------------------------------------------------------- 
 339 void wxPropertyGridInterface::ClearModifiedStatus() 
 341     unsigned int pageIndex 
= 0; 
 345         wxPropertyGridPageState
* page 
= GetPageState(pageIndex
); 
 348         page
->DoGetRoot()->SetFlagRecursively(wxPG_PROP_MODIFIED
, false); 
 349         page
->m_anyModified 
= false; 
 354     // Update active editor control, if any 
 355     GetPropertyGrid()->RefreshEditor(); 
 358 bool wxPropertyGridInterface::SetColumnProportion( unsigned int column
, 
 361     wxCHECK(m_pState
, false); 
 362     wxPropertyGrid
* pg 
= m_pState
->GetGrid(); 
 364     wxCHECK(pg
->HasFlag(wxPG_SPLITTER_AUTO_CENTER
), false); 
 365     m_pState
->DoSetColumnProportion(column
, proportion
); 
 369 // ----------------------------------------------------------------------- 
 370 // wxPropertyGridInterface property value setting and getting 
 371 // ----------------------------------------------------------------------- 
 373 void wxPGGetFailed( const wxPGProperty
* p
, const wxString
& typestr 
) 
 375     wxPGTypeOperationFailed(p
, typestr
, wxS("Get")); 
 378 // ----------------------------------------------------------------------- 
 380 void wxPGTypeOperationFailed( const wxPGProperty
* p
, 
 381                               const wxString
& typestr
, 
 384     wxASSERT( p 
!= NULL 
); 
 385     wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."), 
 386         op
.c_str(), p
->GetLabel().c_str(), p
->GetValue().GetType().c_str(), typestr
.c_str() ); 
 389 // ----------------------------------------------------------------------- 
 391 void wxPropertyGridInterface::SetPropVal( wxPGPropArg id
, wxVariant
& value 
) 
 393     wxPG_PROP_ARG_CALL_PROLOG() 
 399 // ----------------------------------------------------------------------- 
 401 void wxPropertyGridInterface::SetPropertyValueString( wxPGPropArg id
, const wxString
& value 
) 
 403     wxPG_PROP_ARG_CALL_PROLOG() 
 406         m_pState
->DoSetPropertyValueString(p
, value
); 
 409 // ----------------------------------------------------------------------- 
 411 void wxPropertyGridInterface::SetValidationFailureBehavior( int vfbFlags 
) 
 413     GetPropertyGrid()->m_permanentValidationFailureBehavior 
= vfbFlags
; 
 416 // ----------------------------------------------------------------------- 
 418 wxPGProperty
* wxPropertyGridInterface::GetPropertyByNameA( const wxString
& name 
) const 
 420     wxPGProperty
* p 
= GetPropertyByName(name
); 
 421     wxASSERT_MSG(p
,wxString::Format(wxT("no property with name '%s'"),name
.c_str())); 
 425 // ---------------------------------------------------------------------------- 
 427 wxPGProperty
* wxPropertyGridInterface::GetPropertyByLabel( const wxString
& label 
) const 
 431     for ( it 
= GetVIterator( wxPG_ITERATE_PROPERTIES 
); !it
.AtEnd(); it
.Next() ) 
 433         if ( it
.GetProperty()->GetLabel() == label 
) 
 434             return it
.GetProperty(); 
 437     return wxNullProperty
; 
 440 // ---------------------------------------------------------------------------- 
 442 void wxPropertyGridInterface::DoSetPropertyAttribute( wxPGPropArg id
, const wxString
& name
, 
 443                                                       wxVariant
& value
, long argFlags 
) 
 445     wxPG_PROP_ARG_CALL_PROLOG() 
 447     p
->SetAttribute( name
, value 
); 
 449     if ( argFlags 
& wxPG_RECURSE 
) 
 452         for ( i 
= 0; i 
< p
->GetChildCount(); i
++ ) 
 453             DoSetPropertyAttribute(p
->Item(i
), name
, value
, argFlags
); 
 457 // ----------------------------------------------------------------------- 
 459 void wxPropertyGridInterface::SetPropertyAttributeAll( const wxString
& attrName
, 
 462     unsigned int pageIndex 
= 0; 
 466         wxPropertyGridPageState
* page 
= GetPageState(pageIndex
); 
 469         DoSetPropertyAttribute(page
->DoGetRoot(), attrName
, value
, wxPG_RECURSE
); 
 475 // ----------------------------------------------------------------------- 
 477 void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty
* targetArr
, 
 478                                                      wxPGProperty::FlagType flags
, 
 480                                                      int iterFlags 
) const 
 482     wxASSERT( targetArr 
); 
 483     wxPGVIterator it 
= GetVIterator( iterFlags 
); 
 489         const wxPGProperty
* property 
= it
.GetProperty(); 
 493             if ( (property
->GetFlags() & flags
) == flags 
) 
 494                 targetArr
->push_back((wxPGProperty
*)property
); 
 498             if ( (property
->GetFlags() & flags
) != flags 
) 
 499                 targetArr
->push_back((wxPGProperty
*)property
); 
 504 // ----------------------------------------------------------------------- 
 506 void wxPropertyGridInterface::SetBoolChoices( const wxString
& trueChoice
, 
 507                                                  const wxString
& falseChoice 
) 
 509     wxPGGlobalVars
->m_boolChoices
[0] = falseChoice
; 
 510     wxPGGlobalVars
->m_boolChoices
[1] = trueChoice
; 
 513 // ----------------------------------------------------------------------- 
 515 wxPGProperty
* wxPropertyGridInterface::DoGetPropertyByName( const wxString
& name 
) const 
 517     return m_pState
->BaseGetPropertyByName(name
); 
 520 // ----------------------------------------------------------------------- 
 522 wxPGProperty
* wxPropertyGridInterface::GetPropertyByName( const wxString
& name
, 
 523                                                              const wxString
& subname 
) const 
 525     wxPGProperty
* p 
= DoGetPropertyByName(name
); 
 526     if ( !p 
|| !p
->GetChildCount() ) 
 527         return wxNullProperty
; 
 529     return p
->GetPropertyByName(subname
); 
 532 // ----------------------------------------------------------------------- 
 534 // Since GetPropertyByName is used *a lot*, this makes sense 
 535 // since non-virtual method can be called with less code. 
 536 wxPGProperty
* wxPropertyGridInterface::GetPropertyByName( const wxString
& name 
) const 
 538     wxPGProperty
* p 
= DoGetPropertyByName(name
); 
 542     // Check if its "Property.SubProperty" format 
 543     int pos 
= name
.Find(wxT('.')); 
 547     return GetPropertyByName(name
.substr(0,pos
), 
 548                              name
.substr(pos
+1,name
.length()-pos
-1)); 
 551 // ----------------------------------------------------------------------- 
 553 bool wxPropertyGridInterface::HideProperty( wxPGPropArg id
, bool hide
, int flags 
) 
 555     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 557     wxPropertyGrid
* pg 
= m_pState
->GetGrid(); 
 559     if ( pg 
== p
->GetGrid() ) 
 560         return pg
->DoHideProperty(p
, hide
, flags
); 
 562         m_pState
->DoHideProperty(p
, hide
, flags
); 
 567 // ----------------------------------------------------------------------- 
 569 bool wxPropertyGridInterface::Collapse( wxPGPropArg id 
) 
 571     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 572     wxPropertyGrid
* pg 
= p
->GetGridIfDisplayed(); 
 574         return pg
->DoCollapse(p
); 
 576     return p
->GetParentState()->DoCollapse(p
); 
 579 // ----------------------------------------------------------------------- 
 581 bool wxPropertyGridInterface::Expand( wxPGPropArg id 
) 
 583     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 584     wxPropertyGrid
* pg 
= p
->GetGridIfDisplayed(); 
 586         return pg
->DoExpand(p
); 
 588     return p
->GetParentState()->DoExpand(p
); 
 591 // ----------------------------------------------------------------------- 
 593 void wxPropertyGridInterface::Sort( int flags 
) 
 595     wxPropertyGrid
* pg 
= GetPropertyGrid(); 
 597     unsigned int pageIndex 
= 0; 
 601         wxPropertyGridPageState
* page 
= GetPageState(pageIndex
); 
 607     // Fix positions of any open editor controls 
 609         pg
->CorrectEditorWidgetPosY(); 
 612 // ----------------------------------------------------------------------- 
 614 void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id
, const wxString
& newproplabel 
) 
 616     wxPG_PROP_ARG_CALL_PROLOG() 
 618     p
->SetLabel( newproplabel 
); 
 620     wxPropertyGridPageState
* state 
= p
->GetParentState(); 
 621     wxPropertyGrid
* pg 
= state
->GetGrid(); 
 623     if ( pg
->HasFlag(wxPG_AUTO_SORT
) ) 
 624         pg
->SortChildren(p
->GetParent()); 
 626     if ( pg
->GetState() == state 
) 
 628         if ( pg
->HasFlag(wxPG_AUTO_SORT
) ) 
 635 // ----------------------------------------------------------------------- 
 637 bool wxPropertyGridInterface::SetPropertyMaxLength( wxPGPropArg id
, int maxLen 
) 
 639     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 641     wxPropertyGrid
* pg 
= m_pState
->GetGrid(); 
 643     p
->m_maxLen 
= (short) maxLen
; 
 645     // Adjust control if selected currently 
 646     if ( pg 
== p
->GetGrid() && p 
== m_pState
->GetSelection() ) 
 648         wxWindow
* wnd 
= pg
->GetEditorControl(); 
 649         wxTextCtrl
* tc 
= wxDynamicCast(wnd
,wxTextCtrl
); 
 651             tc
->SetMaxLength( maxLen 
); 
 660 // ----------------------------------------------------------------------- 
 663 wxPropertyGridInterface::SetPropertyBackgroundColour( wxPGPropArg id
, 
 664                                                       const wxColour
& colour
, 
 667     wxPG_PROP_ARG_CALL_PROLOG() 
 668     p
->SetBackgroundColour(colour
, flags
); 
 672 // ----------------------------------------------------------------------- 
 674 void wxPropertyGridInterface::SetPropertyTextColour( wxPGPropArg id
, 
 675                                                      const wxColour
& colour
, 
 678     wxPG_PROP_ARG_CALL_PROLOG() 
 679     p
->SetTextColour(colour
, flags
); 
 683 // ----------------------------------------------------------------------- 
 685 void wxPropertyGridInterface::SetPropertyColoursToDefault( wxPGPropArg id 
) 
 687     wxPG_PROP_ARG_CALL_PROLOG() 
 692 // ----------------------------------------------------------------------- 
 694 void wxPropertyGridInterface::SetPropertyCell( wxPGPropArg id
, 
 696                                                const wxString
& text
, 
 697                                                const wxBitmap
& bitmap
, 
 698                                                const wxColour
& fgCol
, 
 699                                                const wxColour
& bgCol 
) 
 701     wxPG_PROP_ARG_CALL_PROLOG() 
 703     wxPGCell
& cell 
= p
->GetCell(column
); 
 704     if ( text
.length() && text 
!= wxPG_LABEL 
) 
 707         cell
.SetBitmap(bitmap
); 
 708     if ( fgCol 
!= wxNullColour 
) 
 709         cell
.SetFgCol(fgCol
); 
 710     if ( bgCol 
!= wxNullColour 
) 
 711         cell
.SetBgCol(bgCol
); 
 714 // ----------------------------------------------------------------------- 
 715 // GetPropertyValueAsXXX methods 
 717 #define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \ 
 718 TRET wxPropertyGridInterface::GetPropertyValueAs##BIGNAME( wxPGPropArg id ) const \ 
 720     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFRETVAL) \ 
 721     wxVariant value = p->GetValue(); \ 
 722     if ( wxStrcmp(value.GetType(), wxPGTypeName_##T) != 0 ) \ 
 724         wxPGGetFailed(p,wxPGTypeName_##T); \ 
 725         return (TRET)DEFRETVAL; \ 
 727     return (TRET)value.Get##BIGNAME(); \ 
 730 // String is different than others. 
 731 wxString 
wxPropertyGridInterface::GetPropertyValueAsString( wxPGPropArg id 
) const 
 733     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxEmptyString
) 
 734     return p
->GetValueAsString(wxPG_FULL_VALUE
); 
 737 bool wxPropertyGridInterface::GetPropertyValueAsBool( wxPGPropArg id 
) const 
 739     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 740     wxVariant value 
= p
->GetValue(); 
 741     if ( wxStrcmp(value
.GetType(), wxPGTypeName_bool
) == 0 ) 
 743         return value
.GetBool(); 
 745     if ( wxStrcmp(value
.GetType(), wxPGTypeName_long
) == 0 ) 
 747         return value
.GetLong()?true:false; 
 749     wxPGGetFailed(p
,wxPGTypeName_bool
); 
 753 IMPLEMENT_GET_VALUE(long,long,Long
,0) 
 754 IMPLEMENT_GET_VALUE(double,double,Double
,0.0) 
 756 bool wxPropertyGridInterface::IsPropertyExpanded( wxPGPropArg id 
) const 
 758     wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) 
 759     return p
->IsExpanded(); 
 762 // ----------------------------------------------------------------------- 
 763 // wxPropertyGridInterface wrappers 
 764 // ----------------------------------------------------------------------- 
 766 bool wxPropertyGridInterface::ChangePropertyValue( wxPGPropArg id
, wxVariant newValue 
) 
 768     return GetPropertyGrid()->ChangePropertyValue(id
, newValue
); 
 771 // ----------------------------------------------------------------------- 
 773 void wxPropertyGridInterface::BeginAddChildren( wxPGPropArg id 
) 
 775     wxPG_PROP_ARG_CALL_PROLOG() 
 776     wxCHECK_RET( p
->HasFlag(wxPG_PROP_AGGREGATE
), wxT("only call on properties with fixed children") ); 
 777     p
->ClearFlag(wxPG_PROP_AGGREGATE
); 
 778     p
->SetFlag(wxPG_PROP_MISC_PARENT
); 
 781 // ----------------------------------------------------------------------- 
 783 bool wxPropertyGridInterface::EditorValidate() 
 785     return GetPropertyGrid()->DoEditorValidate(); 
 788 // ----------------------------------------------------------------------- 
 790 void wxPropertyGridInterface::EndAddChildren( wxPGPropArg id 
) 
 792     wxPG_PROP_ARG_CALL_PROLOG() 
 793     wxCHECK_RET( p
->HasFlag(wxPG_PROP_MISC_PARENT
), wxT("only call on properties for which BeginAddChildren was called prior") ); 
 794     p
->ClearFlag(wxPG_PROP_MISC_PARENT
); 
 795     p
->SetFlag(wxPG_PROP_AGGREGATE
); 
 798 // ----------------------------------------------------------------------- 
 799 // wxPGVIterator_State 
 800 // ----------------------------------------------------------------------- 
 802 // Default returned by wxPropertyGridInterface::GetVIterator(). 
 803 class wxPGVIteratorBase_State 
: public wxPGVIteratorBase
 
 806     wxPGVIteratorBase_State( wxPropertyGridPageState
* state
, int flags 
) 
 808         m_it
.Init( state
, flags 
); 
 810     virtual ~wxPGVIteratorBase_State() { } 
 811     virtual void Next() { m_it
.Next(); } 
 814 wxPGVIterator 
wxPropertyGridInterface::GetVIterator( int flags 
) const 
 816     return wxPGVIterator( new wxPGVIteratorBase_State( m_pState
, flags 
) ); 
 819 // ----------------------------------------------------------------------- 
 820 // wxPGEditableState related functions 
 821 // ----------------------------------------------------------------------- 
 823 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|" 
 824 // in the input string.  This is an internal functions which is 
 825 // used for saving states 
 826 // NB: Similar function exists in aui/framemanager.cpp 
 827 static wxString 
EscapeDelimiters(const wxString
& s
) 
 830     result
.Alloc(s
.length()); 
 831     const wxChar
* ch 
= s
.c_str(); 
 834         if (*ch 
== wxT(';') || *ch 
== wxT('|') || *ch 
== wxT(',')) 
 842 wxString 
wxPropertyGridInterface::SaveEditableState( int includedStates 
) const 
 847     // Save state on page basis 
 848     unsigned int pageIndex 
= 0; 
 849     wxArrayPtrVoid pageStates
; 
 853         wxPropertyGridPageState
* page 
= GetPageState(pageIndex
); 
 856         pageStates
.Add(page
); 
 861     for ( pageIndex
=0; pageIndex 
< pageStates
.size(); pageIndex
++ ) 
 863         wxPropertyGridPageState
* pageState 
= (wxPropertyGridPageState
*) pageStates
[pageIndex
]; 
 865         if ( includedStates 
& SelectionState 
) 
 868             if ( pageState
->GetSelection() ) 
 869                 sel 
= pageState
->GetSelection()->GetName(); 
 870             result 
+= wxS("selection="); 
 871             result 
+= EscapeDelimiters(sel
); 
 874         if ( includedStates 
& ExpandedState 
) 
 876             wxArrayPGProperty ptrs
; 
 877             wxPropertyGridConstIterator it 
= 
 878                 wxPropertyGridConstIterator( pageState
, 
 879                                              wxPG_ITERATE_ALL_PARENTS_RECURSIVELY
|wxPG_ITERATE_HIDDEN
, 
 882             result 
+= wxS("expanded="); 
 888                 const wxPGProperty
* p 
= it
.GetProperty(); 
 890                 if ( !p
->HasFlag(wxPG_PROP_COLLAPSED
) ) 
 891                     result 
+= EscapeDelimiters(p
->GetName()); 
 896             if ( result
.Last() == wxS(',') ) 
 901         if ( includedStates 
& ScrollPosState 
) 
 904             GetPropertyGrid()->GetViewStart(&x
,&y
); 
 905             result 
+= wxString::Format(wxS("scrollpos=%i,%i;"), x
, y
); 
 907         if ( includedStates 
& SplitterPosState 
) 
 909             result 
+= wxS("splitterpos="); 
 911             for ( size_t i
=0; i
<pageState
->GetColumnCount(); i
++ ) 
 912                 result 
+= wxString::Format(wxS("%i,"), pageState
->DoGetSplitterPosition(i
)); 
 914             result
.RemoveLast();  // Remove last comma 
 917         if ( includedStates 
& PageState 
) 
 919             result 
+= wxS("ispageselected="); 
 921             if ( GetPageState(-1) == pageState 
) 
 926         if ( includedStates 
& DescBoxState 
) 
 928             wxVariant v 
= GetEditableStateItem(wxS("descboxheight")); 
 930                 result 
+= wxString::Format(wxS("descboxheight=%i;"), (int)v
.GetLong()); 
 932         result
.RemoveLast();  // Remove last semicolon 
 937     if ( result
.length() ) 
 943 bool wxPropertyGridInterface::RestoreEditableState( const wxString
& src
, int restoreStates 
) 
 945     wxPropertyGrid
* pg 
= GetPropertyGrid(); 
 946     wxPGProperty
* newSelection 
= NULL
; 
 950     long selectedPage 
= -1; 
 951     bool pgSelectionSet 
= false; 
 955     wxArrayString pageStrings 
= ::wxSplit(src
, wxS('|'), wxS('\\')); 
 957     for ( pageIndex
=0; pageIndex
<pageStrings
.size(); pageIndex
++ ) 
 959         wxPropertyGridPageState
* pageState 
= GetPageState(pageIndex
); 
 963         wxArrayString kvpairStrings 
= ::wxSplit(pageStrings
[pageIndex
], wxS(';'), wxS('\\')); 
 965         for ( size_t i
=0; i
<kvpairStrings
.size(); i
++ ) 
 967             const wxString
& kvs 
= kvpairStrings
[i
]; 
 968             int eq_pos 
= kvs
.Find(wxS('=')); 
 969             if ( eq_pos 
!= wxNOT_FOUND 
) 
 971                 wxString key 
= kvs
.substr(0, eq_pos
); 
 972                 wxString value 
= kvs
.substr(eq_pos
+1); 
 974                 // Further split value by commas 
 975                 wxArrayString values 
= ::wxSplit(value
, wxS(','), wxS('\\')); 
 977                 if ( key 
== wxS("expanded") ) 
 979                     if ( restoreStates 
& ExpandedState 
) 
 981                         wxPropertyGridIterator it 
= 
 982                             wxPropertyGridIterator( pageState
, 
 986                         // First collapse all 
 987                         for ( ; !it
.AtEnd(); it
.Next() ) 
 989                             wxPGProperty
* p 
= it
.GetProperty(); 
 990                             pageState
->DoCollapse(p
); 
 993                         // Then expand those which names are in values 
 994                         for ( size_t n
=0; n
<values
.size(); n
++ ) 
 996                             const wxString
& name 
= values
[n
]; 
 997                             wxPGProperty
* prop 
= GetPropertyByName(name
); 
 999                                 pageState
->DoExpand(prop
); 
1003                 else if ( key 
== wxS("scrollpos") ) 
1005                     if ( restoreStates 
& ScrollPosState 
) 
1007                         if ( values
.size() == 2 ) 
1009                             values
[0].ToLong(&vx
); 
1010                             values
[1].ToLong(&vy
); 
1018                 else if ( key 
== wxS("splitterpos") ) 
1020                     if ( restoreStates 
& SplitterPosState 
) 
1022                         for ( size_t n
=1; n
<values
.size(); n
++ ) 
1025                             values
[n
].ToLong(&pos
); 
1027                                 pageState
->DoSetSplitterPosition(pos
, n
); 
1031                 else if ( key 
== wxS("selection") ) 
1033                     if ( restoreStates 
& SelectionState 
) 
1035                         if ( values
.size() > 0 ) 
1037                             if ( pageState
->IsDisplayed() ) 
1039                                 if ( values
[0].length() ) 
1040                                     newSelection 
= GetPropertyByName(value
); 
1041                                 pgSelectionSet 
= true; 
1045                                 if ( values
[0].length() ) 
1046                                     pageState
->DoSetSelection(GetPropertyByName(value
)); 
1048                                     pageState
->DoClearSelection(); 
1053                 else if ( key 
== wxS("ispageselected") ) 
1055                     if ( restoreStates 
& PageState 
) 
1058                         if ( values
.size() == 1 && values
[0].ToLong(&pageSelStatus
) ) 
1060                             if ( pageSelStatus 
) 
1061                                 selectedPage 
= pageIndex
; 
1069                 else if ( key 
== wxS("descboxheight") ) 
1071                     if ( restoreStates 
& DescBoxState 
) 
1074                         if ( values
.size() == 1 && values
[0].ToLong(&descBoxHeight
) ) 
1076                             SetEditableStateItem(wxS("descboxheight"), descBoxHeight
); 
1093     // Force recalculation of virtual heights of all pages 
1094     // (may be needed on unclean source string). 
1096     wxPropertyGridPageState
* pageState 
= GetPageState(pageIndex
); 
1099         pageState
->VirtualHeightChanged(); 
1101         pageState 
= GetPageState(pageIndex
); 
1107     // Selection of visible grid page must be set after Thaw() call 
1108     if ( pgSelectionSet 
) 
1111             pg
->DoSelectProperty(newSelection
); 
1113             pg
->DoClearSelection(); 
1116     if ( selectedPage 
!= -1 ) 
1118         DoSelectPage(selectedPage
); 
1129 #endif  // wxUSE_PROPGRID