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/cursor.h"
36 #include "wx/dialog.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/choice.h"
40 #include "wx/stattext.h"
41 #include "wx/scrolwin.h"
42 #include "wx/dirdlg.h"
43 #include "wx/layout.h"
45 #include "wx/textdlg.h"
46 #include "wx/filedlg.h"
47 #include "wx/statusbr.h"
52 #include <wx/propgrid/property.h>
53 #include <wx/propgrid/propgrid.h>
58 const wxChar
*wxPGTypeName_long
= wxT("long");
59 const wxChar
*wxPGTypeName_bool
= wxT("bool");
60 const wxChar
*wxPGTypeName_double
= wxT("double");
61 const wxChar
*wxPGTypeName_wxString
= wxT("string");
62 const wxChar
*wxPGTypeName_void
= wxT("void*");
63 const wxChar
*wxPGTypeName_wxArrayString
= wxT("arrstring");
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxPoint
, WXDLLIMPEXP_PROPGRID
)
71 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxSize
, WXDLLIMPEXP_PROPGRID
)
72 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(wxArrayInt
, WXDLLIMPEXP_PROPGRID
)
73 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxLongLong
, WXDLLIMPEXP_PROPGRID
)
74 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxULongLong
, WXDLLIMPEXP_PROPGRID
)
76 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxFont
, WXDLLIMPEXP_PROPGRID
)
78 // -----------------------------------------------------------------------
80 // -----------------------------------------------------------------------
82 long wxPGVariantToInt( const wxVariant
& variant
, long defVal
)
84 if ( variant
.IsNull() )
87 if ( variant
.GetType() == wxS("long") )
88 return variant
.GetLong();
90 if ( variant
.GetType() == wxS("bool") )
91 return variant
.GetBool() ?
1 : 0;
93 if ( variant
.GetType() == wxS("wxLongLong") )
99 else if ( ll
<= LONG_MIN
)
106 if ( variant
.GetType() == wxPG_VARIANT_TYPE_STRING
)
107 variant
.GetString().ToLong(&l
, 0);
112 // -----------------------------------------------------------------------
114 bool wxPGVariantToLongLong( const wxVariant
& variant
, wxLongLong_t
* pResult
)
116 if ( variant
.IsNull() )
119 wxString variantType
= variant
.GetType();
121 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
123 *pResult
= variant
.GetLong();
127 if ( variantType
== wxLongLong_VariantType
)
131 *pResult
= ll
.GetValue();
138 // -----------------------------------------------------------------------
140 bool wxPGVariantToULongLong( const wxVariant
& variant
, wxULongLong_t
* pResult
)
142 if ( variant
.IsNull() )
145 wxString variantType
= variant
.GetType();
147 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
149 *pResult
= (unsigned long)variant
.GetLong();
153 if ( variantType
== wxULongLong_VariantType
)
157 *pResult
= ull
.GetValue();
164 // -----------------------------------------------------------------------
166 bool wxPGVariantToDouble( const wxVariant
& variant
, double* pResult
)
168 if ( variant
.IsNull() )
171 wxString variantType
= variant
.GetType();
173 if ( variantType
== wxPG_VARIANT_TYPE_DOUBLE
)
175 *pResult
= variant
.GetDouble();
179 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
181 *pResult
= (double)variant
.GetLong();
185 if ( variantType
== wxLongLong_VariantType
)
189 *pResult
= ll
.ToDouble();
193 if ( variantType
== wxPG_VARIANT_TYPE_STRING
)
194 if ( variant
.GetString().ToDouble(pResult
) )
200 // -----------------------------------------------------------------------
202 // -----------------------------------------------------------------------
204 wxPGProperty
* wxPGPropArgCls
::GetPtr( wxPropertyGridInterface
* iface
) const
206 if ( m_flags
== IsProperty
)
208 wxASSERT_MSG( m_ptr
.property
, wxT("invalid property ptr") );
209 return m_ptr
.property
;
211 else if ( m_flags
& IsWxString
)
212 return iface
->GetPropertyByNameA(*m_ptr
.stringName
);
213 else if ( m_flags
& IsCharPtr
)
214 return iface
->GetPropertyByNameA(m_ptr
.charName
);
216 else if ( m_flags
& IsWCharPtr
)
217 return iface
->GetPropertyByNameA(m_ptr
.wcharName
);
223 // -----------------------------------------------------------------------
224 // wxPropertyGridInterface
225 // -----------------------------------------------------------------------
227 void wxPropertyGridInterface
::RefreshGrid( wxPropertyGridPageState
* state
)
232 wxPropertyGrid
* grid
= state
->GetGrid();
233 if ( grid
->GetState() == state
&& !grid
->IsFrozen() )
239 // -----------------------------------------------------------------------
241 wxPGProperty
* wxPropertyGridInterface
::Append( wxPGProperty
* property
)
243 wxPGProperty
* retp
= m_pState
->DoAppend(property
);
245 wxPropertyGrid
* grid
= m_pState
->GetGrid();
252 // -----------------------------------------------------------------------
254 wxPGProperty
* wxPropertyGridInterface
::AppendIn( wxPGPropArg id
, wxPGProperty
* newproperty
)
256 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
257 wxPGProperty
* pwc
= (wxPGProperty
*) p
;
258 wxPGProperty
* retp
= m_pState
->DoInsert(pwc
, pwc
->GetChildCount(), newproperty
);
262 // -----------------------------------------------------------------------
264 wxPGProperty
* wxPropertyGridInterface
::Insert( wxPGPropArg id
, wxPGProperty
* property
)
266 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
267 wxPGProperty
* retp
= m_pState
->DoInsert(p
->GetParent(), p
->GetArrIndex(), property
);
272 // -----------------------------------------------------------------------
274 wxPGProperty
* wxPropertyGridInterface
::Insert( wxPGPropArg id
, int index
, wxPGProperty
* newproperty
)
276 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
277 wxPGProperty
* retp
= m_pState
->DoInsert((wxPGProperty
*)p
,index
,newproperty
);
282 // -----------------------------------------------------------------------
284 void wxPropertyGridInterface
::DeleteProperty( wxPGPropArg id
)
286 wxPG_PROP_ARG_CALL_PROLOG()
288 wxPropertyGridPageState
* state
= p
->GetParentState();
289 wxPropertyGrid
* grid
= state
->GetGrid();
291 if ( grid
->GetState() == state
)
293 bool selRes
= grid
->DoSelectProperty(NULL
, wxPG_SEL_DELETING
);
294 wxPG_CHECK_RET_DBG( selRes
,
295 wxT("failed to deselect a property (editor probably had invalid value)") );
298 state
->DoDelete( p
);
303 // -----------------------------------------------------------------------
305 wxPGProperty
* wxPropertyGridInterface
::ReplaceProperty( wxPGPropArg id
, wxPGProperty
* property
)
307 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
309 wxPGProperty
* replaced
= p
;
310 wxCHECK_MSG( replaced
&& property
,
312 wxT("NULL property") );
313 wxCHECK_MSG( !replaced
->IsCategory(),
315 wxT("cannot replace this type of property") );
316 wxCHECK_MSG( !m_pState
->IsInNonCatMode(),
318 wxT("cannot replace properties in alphabetic mode") );
320 // Get address to the slot
321 wxPGProperty
* parent
= replaced
->GetParent();
322 int ind
= replaced
->GetIndexInParent();
324 wxPropertyGridPageState
* state
= replaced
->GetParentState();
325 DeleteProperty(replaced
); // Must use generic Delete
326 state
->DoInsert(parent
,ind
,property
);
331 // -----------------------------------------------------------------------
332 // wxPropertyGridInterface property operations
333 // -----------------------------------------------------------------------
335 bool wxPropertyGridInterface
::ClearSelection()
337 wxPropertyGridPageState
* state
= m_pState
;
338 wxPropertyGrid
* pg
= state
->GetGrid();
339 if ( pg
->GetState() == state
)
340 return pg
->DoClearSelection();
342 state
->SetSelection(NULL
);
346 // -----------------------------------------------------------------------
348 void wxPropertyGridInterface
::LimitPropertyEditing( wxPGPropArg id
, bool limit
)
350 wxPG_PROP_ARG_CALL_PROLOG()
352 m_pState
->DoLimitPropertyEditing(p
, limit
);
356 // -----------------------------------------------------------------------
358 bool wxPropertyGridInterface
::EnableProperty( wxPGPropArg id
, bool enable
)
360 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
362 wxPropertyGridPageState
* state
= p
->GetParentState();
363 wxPropertyGrid
* grid
= state
->GetGrid();
367 if ( !(p
->m_flags
& wxPG_PROP_DISABLED
) )
370 // If active, Set active Editor.
371 if ( grid
->GetState() == state
&& p
== grid
->GetSelection() )
372 grid
->DoSelectProperty( p
, wxPG_SEL_FORCE
);
376 if ( p
->m_flags
& wxPG_PROP_DISABLED
)
379 // If active, Disable as active Editor.
380 if ( grid
->GetState() == state
&& p
== grid
->GetSelection() )
381 grid
->DoSelectProperty( p
, wxPG_SEL_FORCE
);
384 state
->DoEnableProperty(p
, enable
);
386 RefreshProperty( p
);
391 // -----------------------------------------------------------------------
393 bool wxPropertyGridInterface
::ExpandAll( bool doExpand
)
395 wxPropertyGridPageState
* state
= m_pState
;
397 if ( !state
->DoGetRoot()->GetChildCount() )
400 wxPropertyGrid
* pg
= state
->GetGrid();
402 if ( GetSelection() && GetSelection() != state
->DoGetRoot() &&
405 if ( !pg
->ClearSelection() )
411 for ( it
= GetVIterator( wxPG_ITERATE_ALL
); !it
.AtEnd(); it
.Next() )
413 wxPGProperty
* p
= (wxPGProperty
*) it
.GetProperty();
414 if ( p
->GetChildCount() )
418 if ( !p
->IsExpanded() )
425 if ( p
->IsExpanded() )
427 state
->DoCollapse(p
);
433 pg
->RecalculateVirtualSize();
440 // -----------------------------------------------------------------------
442 void wxPropertyGridInterface
::SetPropertyValueUnspecified( wxPGPropArg id
)
444 wxPG_PROP_ARG_CALL_PROLOG()
445 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
447 propGrid
->DoSetPropertyValueUnspecified(p
);
449 p
->GetParentState()->DoSetPropertyValueUnspecified(p
);
452 // -----------------------------------------------------------------------
453 // wxPropertyGridInterface property value setting and getting
454 // -----------------------------------------------------------------------
456 void wxPGGetFailed( const wxPGProperty
* p
, const wxString
& typestr
)
458 wxPGTypeOperationFailed(p
, typestr
, wxS("Get"));
461 // -----------------------------------------------------------------------
463 void wxPGTypeOperationFailed( const wxPGProperty
* p
,
464 const wxString
& typestr
,
467 wxASSERT( p
!= NULL
);
468 wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."),
469 op
.c_str(), p
->GetLabel().c_str(), p
->GetValue().GetType().c_str(), typestr
.c_str() );
472 // -----------------------------------------------------------------------
474 void wxPropertyGridInterface
::SetPropVal( wxPGPropArg id
, wxVariant
& value
)
476 wxPG_PROP_ARG_CALL_PROLOG()
481 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
483 propGrid
->DrawItemAndValueRelated( p
);
488 // -----------------------------------------------------------------------
490 void wxPropertyGridInterface
::SetPropertyValueString( wxPGPropArg id
, const wxString
& value
)
492 wxPG_PROP_ARG_CALL_PROLOG()
494 if ( m_pState
->DoSetPropertyValueString(p
,value
) )
496 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
498 propGrid
->DrawItemAndValueRelated( p
);
502 // -----------------------------------------------------------------------
504 void wxPropertyGridInterface
::SetValidationFailureBehavior( int vfbFlags
)
506 GetPropertyGrid()->m_permanentValidationFailureBehavior
= vfbFlags
;
509 // -----------------------------------------------------------------------
511 wxPGProperty
* wxPropertyGridInterface
::GetPropertyByNameA( const wxString
& name
) const
513 wxPGProperty
* p
= GetPropertyByName(name
);
514 wxASSERT_MSG(p
,wxString
::Format(wxT("no property with name '%s'"),name
.c_str()));
518 // ----------------------------------------------------------------------------
520 wxPGProperty
* wxPropertyGridInterface
::GetPropertyByLabel( const wxString
& label
) const
524 for ( it
= GetVIterator( wxPG_ITERATE_PROPERTIES
); !it
.AtEnd(); it
.Next() )
526 if ( it
.GetProperty()->GetLabel() == label
)
527 return it
.GetProperty();
530 return wxNullProperty
;
533 // ----------------------------------------------------------------------------
535 void wxPropertyGridInterface
::DoSetPropertyAttribute( wxPGPropArg id
, const wxString
& name
,
536 wxVariant
& value
, long argFlags
)
538 wxPG_PROP_ARG_CALL_PROLOG()
540 p
->SetAttribute( name
, value
);
542 if ( argFlags
& wxPG_RECURSE
)
545 for ( i
= 0; i
< p
->GetChildCount(); i
++ )
546 DoSetPropertyAttribute(p
->Item(i
), name
, value
, argFlags
);
550 // -----------------------------------------------------------------------
552 void wxPropertyGridInterface
::SetPropertyAttributeAll( const wxString
& attrName
,
555 unsigned int pageIndex
= 0;
559 wxPropertyGridPageState
* page
= GetPageState(pageIndex
);
562 DoSetPropertyAttribute(page
->DoGetRoot(), attrName
, value
, wxPG_RECURSE
);
568 // -----------------------------------------------------------------------
570 void wxPropertyGridInterface
::GetPropertiesWithFlag( wxArrayPGProperty
* targetArr
,
571 wxPGProperty
::FlagType flags
,
573 int iterFlags
) const
575 wxASSERT( targetArr
);
576 wxPGVIterator it
= GetVIterator( iterFlags
);
582 const wxPGProperty
* property
= it
.GetProperty();
586 if ( (property
->GetFlags() & flags
) == flags
)
587 targetArr
->push_back((wxPGProperty
*)property
);
591 if ( (property
->GetFlags() & flags
) != flags
)
592 targetArr
->push_back((wxPGProperty
*)property
);
597 // -----------------------------------------------------------------------
599 void wxPropertyGridInterface
::SetPropertiesFlag( const wxArrayPGProperty
& srcArr
,
600 wxPGProperty
::FlagType flags
,
605 for ( i
=0; i
<srcArr
.size(); i
++ )
607 wxPGProperty
* property
= srcArr
[i
];
610 property
->SetFlag(flags
);
612 property
->ClearFlag(flags
);
615 // If collapsed flag or hidden was manipulated, we need to update virtual
617 wxPropertyGrid
* pg
= GetPropertyGrid();
618 if ( flags
& (wxPG_PROP_COLLAPSED
|wxPG_PROP_HIDDEN
) )
620 GetState()->VirtualHeightChanged();
621 pg
->RecalculateVirtualSize();
625 // -----------------------------------------------------------------------
627 void wxPropertyGridInterface
::SetBoolChoices( const wxString
& trueChoice
,
628 const wxString
& falseChoice
)
630 wxPGGlobalVars
->m_boolChoices
[0] = falseChoice
;
631 wxPGGlobalVars
->m_boolChoices
[1] = trueChoice
;
634 // -----------------------------------------------------------------------
636 wxPGProperty
* wxPropertyGridInterface
::DoGetPropertyByName( const wxString
& name
) const
638 return m_pState
->BaseGetPropertyByName(name
);
641 // -----------------------------------------------------------------------
643 wxPGProperty
* wxPropertyGridInterface
::GetPropertyByName( const wxString
& name
,
644 const wxString
& subname
) const
646 wxPGProperty
* p
= DoGetPropertyByName(name
);
647 if ( !p
|| !p
->GetChildCount() )
648 return wxNullProperty
;
650 return p
->GetPropertyByName(subname
);
653 // -----------------------------------------------------------------------
655 // Since GetPropertyByName is used *a lot*, this makes sense
656 // since non-virtual method can be called with less code.
657 wxPGProperty
* wxPropertyGridInterface
::GetPropertyByName( const wxString
& name
) const
659 wxPGProperty
* p
= DoGetPropertyByName(name
);
663 // Check if its "Property.SubProperty" format
664 int pos
= name
.Find(wxT('.'));
668 return GetPropertyByName(name
.substr(0,pos
),
669 name
.substr(pos
+1,name
.length()-pos
-1));
672 // -----------------------------------------------------------------------
674 bool wxPropertyGridInterface
::HideProperty( wxPGPropArg id
, bool hide
, int flags
)
676 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
678 wxPropertyGrid
* pg
= m_pState
->GetGrid();
680 if ( pg
== p
->GetGrid() )
681 return pg
->DoHideProperty(p
, hide
, flags
);
683 m_pState
->DoHideProperty(p
, hide
, flags
);
688 // -----------------------------------------------------------------------
690 bool wxPropertyGridInterface
::Collapse( wxPGPropArg id
)
692 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
693 wxPropertyGrid
* pg
= p
->GetGridIfDisplayed();
695 return pg
->DoCollapse(p
);
697 return p
->GetParentState()->DoCollapse(p
);
700 // -----------------------------------------------------------------------
702 bool wxPropertyGridInterface
::Expand( wxPGPropArg id
)
704 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
705 wxPropertyGrid
* pg
= p
->GetGridIfDisplayed();
707 return pg
->DoExpand(p
);
709 return p
->GetParentState()->DoExpand(p
);
712 // -----------------------------------------------------------------------
714 void wxPropertyGridInterface
::SetPropertyLabel( wxPGPropArg id
, const wxString
& newproplabel
)
716 wxPG_PROP_ARG_CALL_PROLOG()
718 p
->SetLabel( newproplabel
);
720 wxPropertyGridPageState
* state
= p
->GetParentState();
721 wxPropertyGrid
* pg
= state
->GetGrid();
723 if ( pg
->HasFlag(wxPG_AUTO_SORT
) )
724 pg
->SortChildren(p
->GetParent());
726 if ( pg
->GetState() == state
)
728 if ( pg
->HasFlag(wxPG_AUTO_SORT
) )
735 // -----------------------------------------------------------------------
737 bool wxPropertyGridInterface
::SetPropertyMaxLength( wxPGPropArg id
, int maxLen
)
739 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
741 wxPropertyGrid
* pg
= m_pState
->GetGrid();
743 p
->m_maxLen
= (short) maxLen
;
745 // Adjust control if selected currently
746 if ( pg
== p
->GetGrid() && p
== m_pState
->GetSelection() )
748 wxWindow
* wnd
= pg
->GetEditorControl();
749 wxTextCtrl
* tc
= wxDynamicCast(wnd
,wxTextCtrl
);
751 tc
->SetMaxLength( maxLen
);
760 // -----------------------------------------------------------------------
761 // GetPropertyValueAsXXX methods
763 #define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \
764 TRET wxPropertyGridInterface::GetPropertyValueAs##BIGNAME( wxPGPropArg id ) const \
766 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFRETVAL) \
767 wxVariant value = p->GetValue(); \
768 if ( wxStrcmp(value.GetType(), wxPGTypeName_##T) != 0 ) \
770 wxPGGetFailed(p,wxPGTypeName_##T); \
771 return (TRET)DEFRETVAL; \
773 return (TRET)value.Get##BIGNAME(); \
776 // String is different than others.
777 wxString wxPropertyGridInterface
::GetPropertyValueAsString( wxPGPropArg id
) const
779 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxEmptyString
)
780 return p
->GetValueAsString(wxPG_FULL_VALUE
);
783 bool wxPropertyGridInterface
::GetPropertyValueAsBool( wxPGPropArg id
) const
785 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
786 wxVariant value
= p
->GetValue();
787 if ( wxStrcmp(value
.GetType(), wxPGTypeName_bool
) == 0 )
789 return value
.GetBool();
791 if ( wxStrcmp(value
.GetType(), wxPGTypeName_long
) == 0 )
793 return value
.GetLong()?
true:false;
795 wxPGGetFailed(p
,wxPGTypeName_bool
);
799 IMPLEMENT_GET_VALUE(long,long,Long
,0)
800 IMPLEMENT_GET_VALUE(double,double,Double
,0.0)
801 IMPLEMENT_GET_VALUE(void,void*,VoidPtr
,NULL
)
803 bool wxPropertyGridInterface
::IsPropertyExpanded( wxPGPropArg id
) const
805 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
806 return p
->IsExpanded();
809 // -----------------------------------------------------------------------
810 // wxPropertyGridInterface wrappers
811 // -----------------------------------------------------------------------
813 bool wxPropertyGridInterface
::ChangePropertyValue( wxPGPropArg id
, wxVariant newValue
)
815 return GetPropertyGrid()->ChangePropertyValue(id
, newValue
);
818 // -----------------------------------------------------------------------
820 void wxPropertyGridInterface
::BeginAddChildren( wxPGPropArg id
)
822 wxPG_PROP_ARG_CALL_PROLOG()
823 wxCHECK_RET( p
->HasFlag(wxPG_PROP_AGGREGATE
), wxT("only call on properties with fixed children") );
824 p
->ClearFlag(wxPG_PROP_AGGREGATE
);
825 p
->SetFlag(wxPG_PROP_MISC_PARENT
);
828 // -----------------------------------------------------------------------
830 bool wxPropertyGridInterface
::EditorValidate()
832 return GetPropertyGrid()->DoEditorValidate();
835 // -----------------------------------------------------------------------
837 void wxPropertyGridInterface
::EndAddChildren( wxPGPropArg id
)
839 wxPG_PROP_ARG_CALL_PROLOG()
840 wxCHECK_RET( p
->HasFlag(wxPG_PROP_MISC_PARENT
), wxT("only call on properties for which BeginAddChildren was called prior") );
841 p
->ClearFlag(wxPG_PROP_MISC_PARENT
);
842 p
->SetFlag(wxPG_PROP_AGGREGATE
);
845 // -----------------------------------------------------------------------
846 // wxPGVIterator_State
847 // -----------------------------------------------------------------------
849 // Default returned by wxPropertyGridInterface::GetVIterator().
850 class wxPGVIteratorBase_State
: public wxPGVIteratorBase
853 wxPGVIteratorBase_State( wxPropertyGridPageState
* state
, int flags
)
855 m_it
.Init( state
, flags
);
857 virtual ~wxPGVIteratorBase_State() { }
858 virtual void Next() { m_it
.Next(); }
861 wxPGVIterator wxPropertyGridInterface
::GetVIterator( int flags
) const
863 return wxPGVIterator( new wxPGVIteratorBase_State( m_pState
, flags
) );
866 // -----------------------------------------------------------------------
867 // wxPGEditableState related functions
868 // -----------------------------------------------------------------------
870 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
871 // in the input string. This is an internal functions which is
872 // used for saving states
873 // NB: Similar function exists in aui/framemanager.cpp
874 static wxString
EscapeDelimiters(const wxString
& s
)
877 result
.Alloc(s
.length());
878 const wxChar
* ch
= s
.c_str();
881 if (*ch
== wxT(';') || *ch
== wxT('|') || *ch
== wxT(','))
889 wxString wxPropertyGridInterface
::SaveEditableState( int includedStates
) const
894 // Save state on page basis
895 unsigned int pageIndex
= 0;
896 wxArrayPtrVoid pageStates
;
900 wxPropertyGridPageState
* page
= GetPageState(pageIndex
);
903 pageStates
.Add(page
);
908 for ( pageIndex
=0; pageIndex
< pageStates
.size(); pageIndex
++ )
910 wxPropertyGridPageState
* pageState
= (wxPropertyGridPageState
*) pageStates
[pageIndex
];
912 if ( includedStates
& SelectionState
)
915 if ( pageState
->GetSelection() )
916 sel
= pageState
->GetSelection()->GetName();
917 result
+= wxS("selection=");
918 result
+= EscapeDelimiters(sel
);
921 if ( includedStates
& ExpandedState
)
923 wxArrayPGProperty ptrs
;
924 wxPropertyGridConstIterator it
=
925 wxPropertyGridConstIterator( pageState
,
926 wxPG_ITERATE_ALL_PARENTS_RECURSIVELY
|wxPG_ITERATE_HIDDEN
,
929 result
+= wxS("expanded=");
935 const wxPGProperty
* p
= it
.GetProperty();
937 if ( !p
->HasFlag(wxPG_PROP_COLLAPSED
) )
938 result
+= EscapeDelimiters(p
->GetName());
943 if ( result
.Last() == wxS(',') )
948 if ( includedStates
& ScrollPosState
)
951 GetPropertyGrid()->GetViewStart(&x
,&y
);
952 result
+= wxString
::Format(wxS("scrollpos=%i,%i;"), x
, y
);
954 if ( includedStates
& SplitterPosState
)
956 result
+= wxS("splitterpos=");
958 for ( size_t i
=0; i
<pageState
->GetColumnCount(); i
++ )
959 result
+= wxString
::Format(wxS("%i,"), pageState
->DoGetSplitterPosition(i
));
961 result
.RemoveLast(); // Remove last comma
964 if ( includedStates
& PageState
)
966 result
+= wxS("ispageselected=");
968 if ( GetPageState(-1) == pageState
)
973 result
.RemoveLast(); // Remove last semicolon
978 if ( result
.length() )
984 bool wxPropertyGridInterface
::RestoreEditableState( const wxString
& src
, int restoreStates
)
986 wxPropertyGrid
* pg
= GetPropertyGrid();
987 wxPGProperty
* newSelection
= NULL
;
991 long selectedPage
= -1;
992 bool pgSelectionSet
= false;
996 wxArrayString pageStrings
= ::wxSplit(src
, wxS('|'), wxS('\\'));
998 for ( pageIndex
=0; pageIndex
<pageStrings
.size(); pageIndex
++ )
1000 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
1004 wxArrayString kvpairStrings
= ::wxSplit(pageStrings
[pageIndex
], wxS(';'), wxS('\\'));
1006 for ( size_t i
=0; i
<kvpairStrings
.size(); i
++ )
1008 const wxString
& kvs
= kvpairStrings
[i
];
1009 int eq_pos
= kvs
.Find(wxS('='));
1010 if ( eq_pos
!= wxNOT_FOUND
)
1012 wxString key
= kvs
.substr(0, eq_pos
);
1013 wxString value
= kvs
.substr(eq_pos
+1);
1015 // Further split value by commas
1016 wxArrayString values
= ::wxSplit(value
, wxS(','), wxS('\\'));
1018 if ( key
== wxS("expanded") )
1020 if ( restoreStates
& ExpandedState
)
1022 wxPropertyGridIterator it
=
1023 wxPropertyGridIterator( pageState
,
1027 // First collapse all
1028 for ( ; !it
.AtEnd(); it
.Next() )
1030 wxPGProperty
* p
= it
.GetProperty();
1031 pageState
->DoCollapse(p
);
1034 // Then expand those which names are in values
1035 for ( size_t n
=0; n
<values
.size(); n
++ )
1037 const wxString
& name
= values
[n
];
1038 wxPGProperty
* prop
= GetPropertyByName(name
);
1040 pageState
->DoExpand(prop
);
1044 else if ( key
== wxS("scrollpos") )
1046 if ( restoreStates
& ScrollPosState
)
1048 if ( values
.size() == 2 )
1050 values
[0].ToLong(&vx
);
1051 values
[1].ToLong(&vy
);
1059 else if ( key
== wxS("splitterpos") )
1061 if ( restoreStates
& SplitterPosState
)
1063 for ( size_t n
=1; n
<values
.size(); n
++ )
1066 values
[n
].ToLong(&pos
);
1068 pageState
->DoSetSplitterPosition(pos
, n
);
1072 else if ( key
== wxS("selection") )
1074 if ( restoreStates
& SelectionState
)
1076 if ( values
.size() > 0 )
1078 if ( pageState
->IsDisplayed() )
1080 if ( values
[0].length() )
1081 newSelection
= GetPropertyByName(value
);
1082 pgSelectionSet
= true;
1086 if ( values
[0].length() )
1087 pageState
->SetSelection(GetPropertyByName(value
));
1089 pageState
->DoClearSelection();
1094 else if ( key
== wxS("ispageselected") )
1096 if ( restoreStates
& PageState
)
1099 if ( values
.size() == 1 && values
[0].ToLong(&pageSelStatus
) )
1101 if ( pageSelStatus
)
1102 selectedPage
= pageIndex
;
1119 // Force recalculation of virtual heights of all pages
1120 // (may be needed on unclean source string).
1122 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
1125 pageState
->VirtualHeightChanged();
1127 pageState
= GetPageState(pageIndex
);
1133 // Selection of visible grid page must be set after Thaw() call
1134 if ( pgSelectionSet
)
1137 pg
->SelectProperty(newSelection
);
1139 pg
->ClearSelection();
1142 if ( selectedPage
!= -1 )
1144 DoSelectPage(selectedPage
);
1155 #endif // wxUSE_PROPGRID