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"
21 #include "wx/object.h"
23 #include "wx/string.h"
26 #include "wx/window.h"
29 #include "wx/dcmemory.h"
30 #include "wx/button.h"
33 #include "wx/cursor.h"
34 #include "wx/dialog.h"
35 #include "wx/settings.h"
36 #include "wx/msgdlg.h"
37 #include "wx/choice.h"
38 #include "wx/stattext.h"
39 #include "wx/scrolwin.h"
40 #include "wx/dirdlg.h"
41 #include "wx/layout.h"
43 #include "wx/textdlg.h"
44 #include "wx/filedlg.h"
45 #include "wx/statusbr.h"
50 #include <wx/propgrid/property.h>
51 #include <wx/propgrid/propgrid.h>
56 const wxChar
*wxPGTypeName_long
= wxT("long");
57 const wxChar
*wxPGTypeName_bool
= wxT("bool");
58 const wxChar
*wxPGTypeName_double
= wxT("double");
59 const wxChar
*wxPGTypeName_wxString
= wxT("string");
60 const wxChar
*wxPGTypeName_void
= wxT("void*");
61 const wxChar
*wxPGTypeName_wxArrayString
= wxT("arrstring");
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxPoint
, WXDLLIMPEXP_PROPGRID
)
69 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxSize
, WXDLLIMPEXP_PROPGRID
)
70 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(wxArrayInt
, WXDLLIMPEXP_PROPGRID
)
71 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxLongLong
, WXDLLIMPEXP_PROPGRID
)
72 WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxULongLong
, WXDLLIMPEXP_PROPGRID
)
74 IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxFont
, WXDLLIMPEXP_PROPGRID
)
76 // -----------------------------------------------------------------------
78 // -----------------------------------------------------------------------
80 long wxPGVariantToInt( const wxVariant
& variant
, long defVal
)
82 if ( variant
.IsNull() )
85 if ( variant
.GetType() == wxS("long") )
86 return variant
.GetLong();
88 if ( variant
.GetType() == wxS("bool") )
89 return variant
.GetBool() ? 1 : 0;
91 if ( variant
.GetType() == wxS("wxLongLong") )
97 else if ( ll
<= LONG_MIN
)
104 if ( variant
.GetType() == wxPG_VARIANT_TYPE_STRING
)
105 variant
.GetString().ToLong(&l
, 0);
110 // -----------------------------------------------------------------------
112 bool wxPGVariantToLongLong( const wxVariant
& variant
, wxLongLong_t
* pResult
)
114 if ( variant
.IsNull() )
117 wxString variantType
= variant
.GetType();
119 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
121 *pResult
= variant
.GetLong();
125 if ( variantType
== wxLongLong_VariantType
)
129 *pResult
= ll
.GetValue();
136 // -----------------------------------------------------------------------
138 bool wxPGVariantToULongLong( const wxVariant
& variant
, wxULongLong_t
* pResult
)
140 if ( variant
.IsNull() )
143 wxString variantType
= variant
.GetType();
145 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
147 *pResult
= (unsigned long)variant
.GetLong();
151 if ( variantType
== wxULongLong_VariantType
)
155 *pResult
= ull
.GetValue();
162 // -----------------------------------------------------------------------
164 bool wxPGVariantToDouble( const wxVariant
& variant
, double* pResult
)
166 if ( variant
.IsNull() )
169 wxString variantType
= variant
.GetType();
171 if ( variantType
== wxPG_VARIANT_TYPE_DOUBLE
)
173 *pResult
= variant
.GetDouble();
177 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
179 *pResult
= (double)variant
.GetLong();
183 if ( variantType
== wxLongLong_VariantType
)
187 *pResult
= ll
.ToDouble();
191 if ( variantType
== wxPG_VARIANT_TYPE_STRING
)
192 if ( variant
.GetString().ToDouble(pResult
) )
198 // -----------------------------------------------------------------------
200 // -----------------------------------------------------------------------
202 wxPGProperty
* wxPGPropArgCls::GetPtr( wxPropertyGridInterface
* iface
) const
204 if ( m_flags
== IsProperty
)
206 wxASSERT_MSG( m_ptr
.property
, wxT("invalid property ptr") );
207 return m_ptr
.property
;
209 else if ( m_flags
& IsWxString
)
210 return iface
->GetPropertyByNameA(*m_ptr
.stringName
);
211 else if ( m_flags
& IsCharPtr
)
212 return iface
->GetPropertyByNameA(m_ptr
.charName
);
214 else if ( m_flags
& IsWCharPtr
)
215 return iface
->GetPropertyByNameA(m_ptr
.wcharName
);
221 // -----------------------------------------------------------------------
222 // Choice related methods
223 // -----------------------------------------------------------------------
225 void wxPropertyGridInterface::AddPropertyChoice( wxPGPropArg id
,
226 const wxString
& label
,
229 wxPG_PROP_ARG_CALL_PROLOG()
231 p
->InsertChoice(label
,-1,value
);
235 void wxPropertyGridInterface::InsertPropertyChoice( wxPGPropArg id
,
236 const wxString
& label
,
240 wxPG_PROP_ARG_CALL_PROLOG()
242 p
->InsertChoice(label
,index
,value
);
246 void wxPropertyGridInterface::DeletePropertyChoice( wxPGPropArg id
,
249 wxPG_PROP_ARG_CALL_PROLOG()
251 p
->DeleteChoice(index
);
254 // -----------------------------------------------------------------------
256 void wxPropertyGridInterface::RefreshGrid( wxPropertyGridPageState
* state
)
261 wxPropertyGrid
* grid
= state
->GetGrid();
262 if ( grid
->GetState() == state
&& !grid
->IsFrozen() )
268 // -----------------------------------------------------------------------
270 wxPGProperty
* wxPropertyGridInterface::Append( wxPGProperty
* property
)
272 wxPGProperty
* retp
= m_pState
->DoAppend(property
);
274 wxPropertyGrid
* grid
= m_pState
->GetGrid();
281 // -----------------------------------------------------------------------
283 wxPGProperty
* wxPropertyGridInterface::AppendIn( wxPGPropArg id
, wxPGProperty
* newproperty
)
285 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
286 wxPGProperty
* pwc
= (wxPGProperty
*) p
;
287 wxPGProperty
* retp
= m_pState
->DoInsert(pwc
, pwc
->GetChildCount(), newproperty
);
291 // -----------------------------------------------------------------------
293 wxPGProperty
* wxPropertyGridInterface::Insert( wxPGPropArg id
, wxPGProperty
* property
)
295 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
296 wxPGProperty
* retp
= m_pState
->DoInsert(p
->GetParent(), p
->GetArrIndex(), property
);
301 // -----------------------------------------------------------------------
303 wxPGProperty
* wxPropertyGridInterface::Insert( wxPGPropArg id
, int index
, wxPGProperty
* newproperty
)
305 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
306 wxPGProperty
* retp
= m_pState
->DoInsert((wxPGProperty
*)p
,index
,newproperty
);
311 // -----------------------------------------------------------------------
313 void wxPropertyGridInterface::DeleteProperty( wxPGPropArg id
)
315 wxPG_PROP_ARG_CALL_PROLOG()
317 wxPropertyGridPageState
* state
= p
->GetParentState();
318 wxPropertyGrid
* grid
= state
->GetGrid();
320 if ( grid
->GetState() == state
)
322 bool selRes
= grid
->DoSelectProperty(NULL
, wxPG_SEL_DELETING
);
323 wxPG_CHECK_RET_DBG( selRes
,
324 wxT("failed to deselect a property (editor probably had invalid value)") );
327 state
->DoDelete( p
);
332 // -----------------------------------------------------------------------
334 wxPGProperty
* wxPropertyGridInterface::ReplaceProperty( wxPGPropArg id
, wxPGProperty
* property
)
336 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
338 wxPGProperty
* replaced
= p
;
339 wxCHECK_MSG( replaced
&& property
,
341 wxT("NULL property") );
342 wxCHECK_MSG( !replaced
->IsCategory(),
344 wxT("cannot replace this type of property") );
345 wxCHECK_MSG( !m_pState
->IsInNonCatMode(),
347 wxT("cannot replace properties in alphabetic mode") );
349 // Get address to the slot
350 wxPGProperty
* parent
= replaced
->GetParent();
351 int ind
= replaced
->GetIndexInParent();
353 wxPropertyGridPageState
* state
= replaced
->GetParentState();
354 DeleteProperty(replaced
); // Must use generic Delete
355 state
->DoInsert(parent
,ind
,property
);
360 // -----------------------------------------------------------------------
361 // wxPropertyGridInterface property operations
362 // -----------------------------------------------------------------------
364 bool wxPropertyGridInterface::ClearSelection()
366 wxPropertyGridPageState
* state
= m_pState
;
367 wxPropertyGrid
* pg
= state
->GetGrid();
368 if ( pg
->GetState() == state
)
369 return pg
->DoClearSelection();
371 state
->SetSelection(NULL
);
375 // -----------------------------------------------------------------------
377 void wxPropertyGridInterface::LimitPropertyEditing( wxPGPropArg id
, bool limit
)
379 wxPG_PROP_ARG_CALL_PROLOG()
381 m_pState
->DoLimitPropertyEditing(p
, limit
);
385 // -----------------------------------------------------------------------
387 bool wxPropertyGridInterface::EnableProperty( wxPGPropArg id
, bool enable
)
389 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
391 wxPropertyGridPageState
* state
= p
->GetParentState();
392 wxPropertyGrid
* grid
= state
->GetGrid();
396 if ( !(p
->m_flags
& wxPG_PROP_DISABLED
) )
399 // If active, Set active Editor.
400 if ( grid
->GetState() == state
&& p
== grid
->GetSelection() )
401 grid
->DoSelectProperty( p
, wxPG_SEL_FORCE
);
405 if ( p
->m_flags
& wxPG_PROP_DISABLED
)
408 // If active, Disable as active Editor.
409 if ( grid
->GetState() == state
&& p
== grid
->GetSelection() )
410 grid
->DoSelectProperty( p
, wxPG_SEL_FORCE
);
413 state
->DoEnableProperty(p
, enable
);
415 RefreshProperty( p
);
420 // -----------------------------------------------------------------------
422 bool wxPropertyGridInterface::ExpandAll( bool doExpand
)
424 wxPropertyGridPageState
* state
= m_pState
;
426 if ( !state
->DoGetRoot()->GetChildCount() )
429 wxPropertyGrid
* pg
= state
->GetGrid();
431 if ( GetSelection() && GetSelection() != state
->DoGetRoot() &&
434 if ( !pg
->ClearSelection() )
440 for ( it
= GetVIterator( wxPG_ITERATE_ALL
); !it
.AtEnd(); it
.Next() )
442 wxPGProperty
* p
= (wxPGProperty
*) it
.GetProperty();
443 if ( p
->GetChildCount() )
447 if ( !p
->IsExpanded() )
454 if ( p
->IsExpanded() )
456 state
->DoCollapse(p
);
462 pg
->RecalculateVirtualSize();
469 // -----------------------------------------------------------------------
471 void wxPropertyGridInterface::SetPropertyValueUnspecified( wxPGPropArg id
)
473 wxPG_PROP_ARG_CALL_PROLOG()
474 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
476 propGrid
->DoSetPropertyValueUnspecified(p
);
478 p
->GetParentState()->DoSetPropertyValueUnspecified(p
);
481 // -----------------------------------------------------------------------
482 // wxPropertyGridInterface property value setting and getting
483 // -----------------------------------------------------------------------
485 void wxPGGetFailed( const wxPGProperty
* p
, const wxString
& typestr
)
487 wxPGTypeOperationFailed(p
, typestr
, wxS("Get"));
490 // -----------------------------------------------------------------------
492 void wxPGTypeOperationFailed( const wxPGProperty
* p
,
493 const wxString
& typestr
,
496 wxASSERT( p
!= NULL
);
497 wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."),
498 op
.c_str(), p
->GetLabel().c_str(), p
->GetValue().GetType().c_str(), typestr
.c_str() );
501 // -----------------------------------------------------------------------
503 void wxPropertyGridInterface::SetPropVal( wxPGPropArg id
, wxVariant
& value
)
505 wxPG_PROP_ARG_CALL_PROLOG()
510 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
512 propGrid
->DrawItemAndValueRelated( p
);
517 // -----------------------------------------------------------------------
519 void wxPropertyGridInterface::SetPropertyValueString( wxPGPropArg id
, const wxString
& value
)
521 wxPG_PROP_ARG_CALL_PROLOG()
523 if ( m_pState
->DoSetPropertyValueString(p
,value
) )
525 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
527 propGrid
->DrawItemAndValueRelated( p
);
531 // -----------------------------------------------------------------------
533 void wxPropertyGridInterface::SetValidationFailureBehavior( int vfbFlags
)
535 GetPropertyGrid()->m_permanentValidationFailureBehavior
= vfbFlags
;
538 // -----------------------------------------------------------------------
540 wxPGProperty
* wxPropertyGridInterface::GetPropertyByNameA( const wxString
& name
) const
542 wxPGProperty
* p
= GetPropertyByName(name
);
543 wxASSERT_MSG(p
,wxString::Format(wxT("no property with name '%s'"),name
.c_str()));
547 // ----------------------------------------------------------------------------
549 wxPGProperty
* wxPropertyGridInterface::GetPropertyByLabel( const wxString
& label
) const
553 for ( it
= GetVIterator( wxPG_ITERATE_PROPERTIES
); !it
.AtEnd(); it
.Next() )
555 if ( it
.GetProperty()->GetLabel() == label
)
556 return it
.GetProperty();
559 return wxNullProperty
;
562 // ----------------------------------------------------------------------------
564 void wxPropertyGridInterface::DoSetPropertyAttribute( wxPGPropArg id
, const wxString
& name
,
565 wxVariant
& value
, long argFlags
)
567 wxPG_PROP_ARG_CALL_PROLOG()
569 p
->SetAttribute( name
, value
);
571 if ( argFlags
& wxPG_RECURSE
)
574 for ( i
= 0; i
< p
->GetChildCount(); i
++ )
575 DoSetPropertyAttribute(p
->Item(i
), name
, value
, argFlags
);
579 // -----------------------------------------------------------------------
581 void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty
* targetArr
,
582 wxPGProperty::FlagType flags
,
584 int iterFlags
) const
586 wxASSERT( targetArr
);
587 wxPGVIterator it
= GetVIterator( iterFlags
);
593 const wxPGProperty
* property
= it
.GetProperty();
597 if ( (property
->GetFlags() & flags
) == flags
)
598 targetArr
->push_back((wxPGProperty
*)property
);
602 if ( (property
->GetFlags() & flags
) != flags
)
603 targetArr
->push_back((wxPGProperty
*)property
);
608 // -----------------------------------------------------------------------
610 void wxPropertyGridInterface::SetPropertiesFlag( const wxArrayPGProperty
& srcArr
,
611 wxPGProperty::FlagType flags
,
616 for ( i
=0; i
<srcArr
.size(); i
++ )
618 wxPGProperty
* property
= srcArr
[i
];
621 property
->SetFlag(flags
);
623 property
->ClearFlag(flags
);
626 // If collapsed flag or hidden was manipulated, we need to update virtual
628 wxPropertyGrid
* pg
= GetPropertyGrid();
629 if ( flags
& (wxPG_PROP_COLLAPSED
|wxPG_PROP_HIDDEN
) )
631 GetState()->VirtualHeightChanged();
632 pg
->RecalculateVirtualSize();
636 // -----------------------------------------------------------------------
638 void wxPropertyGridInterface::SetBoolChoices( const wxString
& trueChoice
,
639 const wxString
& falseChoice
)
641 wxPGGlobalVars
->m_boolChoices
[0] = falseChoice
;
642 wxPGGlobalVars
->m_boolChoices
[1] = trueChoice
;
645 // -----------------------------------------------------------------------
647 wxPGChoices gs_emptyChoices
;
649 wxPGChoices
& wxPropertyGridInterface::GetPropertyChoices( wxPGPropArg id
)
651 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(gs_emptyChoices
)
654 ci
.m_choices
= (wxPGChoices
*) NULL
;
656 p
->GetChoiceInfo(&ci
);
659 return gs_emptyChoices
;
661 return *ci
.m_choices
;
664 // -----------------------------------------------------------------------
666 wxPGProperty
* wxPropertyGridInterface::DoGetPropertyByName( const wxString
& name
) const
668 return m_pState
->BaseGetPropertyByName(name
);
671 // -----------------------------------------------------------------------
673 wxPGProperty
* wxPropertyGridInterface::GetPropertyByName( const wxString
& name
,
674 const wxString
& subname
) const
676 wxPGProperty
* p
= DoGetPropertyByName(name
);
677 if ( !p
|| !p
->GetChildCount() )
678 return wxNullProperty
;
680 return p
->GetPropertyByName(subname
);
683 // -----------------------------------------------------------------------
685 // Since GetPropertyByName is used *a lot*, this makes sense
686 // since non-virtual method can be called with less code.
687 wxPGProperty
* wxPropertyGridInterface::GetPropertyByName( const wxString
& name
) const
689 wxPGProperty
* p
= DoGetPropertyByName(name
);
693 // Check if its "Property.SubProperty" format
694 int pos
= name
.Find(wxT('.'));
698 return GetPropertyByName(name
.substr(0,pos
),
699 name
.substr(pos
+1,name
.length()-pos
-1));
702 // -----------------------------------------------------------------------
704 bool wxPropertyGridInterface::HideProperty( wxPGPropArg id
, bool hide
, int flags
)
706 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
708 wxPropertyGrid
* pg
= m_pState
->GetGrid();
710 if ( pg
== p
->GetGrid() )
711 return pg
->DoHideProperty(p
, hide
, flags
);
713 m_pState
->DoHideProperty(p
, hide
, flags
);
718 // -----------------------------------------------------------------------
720 bool wxPropertyGridInterface::Collapse( wxPGPropArg id
)
722 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
723 wxPropertyGrid
* pg
= p
->GetGridIfDisplayed();
725 return pg
->DoCollapse(p
);
727 return p
->GetParentState()->DoCollapse(p
);
730 // -----------------------------------------------------------------------
732 bool wxPropertyGridInterface::Expand( wxPGPropArg id
)
734 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
735 wxPropertyGrid
* pg
= p
->GetGridIfDisplayed();
737 return pg
->DoExpand(p
);
739 return p
->GetParentState()->DoExpand(p
);
742 // -----------------------------------------------------------------------
744 void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id
, const wxString
& newproplabel
)
746 wxPG_PROP_ARG_CALL_PROLOG()
748 p
->SetLabel( newproplabel
);
750 wxPropertyGridPageState
* state
= p
->GetParentState();
751 wxPropertyGrid
* pg
= state
->GetGrid();
753 if ( pg
->HasFlag(wxPG_AUTO_SORT
) )
754 pg
->SortChildren(p
->GetParent());
756 if ( pg
->GetState() == state
)
758 if ( pg
->HasFlag(wxPG_AUTO_SORT
) )
765 // -----------------------------------------------------------------------
767 bool wxPropertyGridInterface::SetPropertyMaxLength( wxPGPropArg id
, int maxLen
)
769 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
771 wxPropertyGrid
* pg
= m_pState
->GetGrid();
773 p
->m_maxLen
= (short) maxLen
;
775 // Adjust control if selected currently
776 if ( pg
== p
->GetGrid() && p
== m_pState
->GetSelection() )
778 wxWindow
* wnd
= pg
->GetEditorControl();
779 wxTextCtrl
* tc
= wxDynamicCast(wnd
,wxTextCtrl
);
781 tc
->SetMaxLength( maxLen
);
790 // -----------------------------------------------------------------------
791 // GetPropertyValueAsXXX methods
793 #define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \
794 TRET wxPropertyGridInterface::GetPropertyValueAs##BIGNAME( wxPGPropArg id ) const \
796 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFRETVAL) \
797 wxVariant value = p->GetValue(); \
798 if ( wxStrcmp(value.GetType(), wxPGTypeName_##T) != 0 ) \
800 wxPGGetFailed(p,wxPGTypeName_##T); \
801 return (TRET)DEFRETVAL; \
803 return (TRET)value.Get##BIGNAME(); \
806 // String is different than others.
807 wxString
wxPropertyGridInterface::GetPropertyValueAsString( wxPGPropArg id
) const
809 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxEmptyString
)
810 return p
->GetValueAsString(wxPG_FULL_VALUE
);
813 bool wxPropertyGridInterface::GetPropertyValueAsBool( wxPGPropArg id
) const
815 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
816 wxVariant value
= p
->GetValue();
817 if ( wxStrcmp(value
.GetType(), wxPGTypeName_bool
) == 0 )
819 return value
.GetBool();
821 if ( wxStrcmp(value
.GetType(), wxPGTypeName_long
) == 0 )
823 return value
.GetLong()?true:false;
825 wxPGGetFailed(p
,wxPGTypeName_bool
);
829 IMPLEMENT_GET_VALUE(long,long,Long
,0)
830 IMPLEMENT_GET_VALUE(double,double,Double
,0.0)
831 IMPLEMENT_GET_VALUE(void,void*,VoidPtr
,NULL
)
833 bool wxPropertyGridInterface::IsPropertyExpanded( wxPGPropArg id
) const
835 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
836 return p
->IsExpanded();
839 // -----------------------------------------------------------------------
840 // wxPropertyGridInterface wrappers
841 // -----------------------------------------------------------------------
843 bool wxPropertyGridInterface::ChangePropertyValue( wxPGPropArg id
, wxVariant newValue
)
845 return GetPropertyGrid()->ChangePropertyValue(id
, newValue
);
848 // -----------------------------------------------------------------------
850 void wxPropertyGridInterface::BeginAddChildren( wxPGPropArg id
)
852 wxPG_PROP_ARG_CALL_PROLOG()
853 wxCHECK_RET( p
->HasFlag(wxPG_PROP_AGGREGATE
), wxT("only call on properties with fixed children") );
854 p
->ClearFlag(wxPG_PROP_AGGREGATE
);
855 p
->SetFlag(wxPG_PROP_MISC_PARENT
);
858 // -----------------------------------------------------------------------
860 bool wxPropertyGridInterface::EditorValidate()
862 return GetPropertyGrid()->DoEditorValidate();
865 // -----------------------------------------------------------------------
867 void wxPropertyGridInterface::EndAddChildren( wxPGPropArg id
)
869 wxPG_PROP_ARG_CALL_PROLOG()
870 wxCHECK_RET( p
->HasFlag(wxPG_PROP_MISC_PARENT
), wxT("only call on properties for which BeginAddChildren was called prior") );
871 p
->ClearFlag(wxPG_PROP_MISC_PARENT
);
872 p
->SetFlag(wxPG_PROP_AGGREGATE
);
875 // -----------------------------------------------------------------------
876 // wxPGVIterator_State
877 // -----------------------------------------------------------------------
879 // Default returned by wxPropertyGridInterface::GetVIterator().
880 class wxPGVIteratorBase_State
: public wxPGVIteratorBase
883 wxPGVIteratorBase_State( wxPropertyGridPageState
* state
, int flags
)
885 m_it
.Init( state
, flags
);
887 virtual ~wxPGVIteratorBase_State() { }
888 virtual void Next() { m_it
.Next(); }
891 wxPGVIterator
wxPropertyGridInterface::GetVIterator( int flags
) const
893 return wxPGVIterator( new wxPGVIteratorBase_State( m_pState
, flags
) );
896 // -----------------------------------------------------------------------
897 // wxPGEditableState related functions
898 // -----------------------------------------------------------------------
900 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
901 // in the input string. This is an internal functions which is
902 // used for saving states
903 // NB: Similar function exists in aui/framemanager.cpp
904 static wxString
EscapeDelimiters(const wxString
& s
)
907 result
.Alloc(s
.length());
908 const wxChar
* ch
= s
.c_str();
911 if (*ch
== wxT(';') || *ch
== wxT('|') || *ch
== wxT(','))
919 wxString
wxPropertyGridInterface::SaveEditableState( int includedStates
) const
924 // Save state on page basis
925 size_t pageIndex
= 0;
926 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
927 wxArrayPtrVoid pageStates
;
930 pageStates
.Add(pageState
);
932 pageState
= GetPageState(pageIndex
);
935 for ( pageIndex
=0; pageIndex
< pageStates
.size(); pageIndex
++ )
937 wxPropertyGridPageState
* pageState
= (wxPropertyGridPageState
*) pageStates
[pageIndex
];
939 if ( includedStates
& SelectionState
)
942 if ( pageState
->GetSelection() )
943 sel
= pageState
->GetSelection()->GetName();
944 result
+= wxS("selection=");
945 result
+= EscapeDelimiters(sel
);
948 if ( includedStates
& ExpandedState
)
950 wxArrayPGProperty ptrs
;
951 wxPropertyGridConstIterator it
=
952 wxPropertyGridConstIterator( pageState
,
953 wxPG_ITERATE_ALL_PARENTS_RECURSIVELY
|wxPG_ITERATE_HIDDEN
,
956 result
+= wxS("expanded=");
962 const wxPGProperty
* p
= it
.GetProperty();
964 if ( !p
->HasFlag(wxPG_PROP_COLLAPSED
) )
965 result
+= EscapeDelimiters(p
->GetName());
970 if ( result
.Last() == wxS(',') )
975 if ( includedStates
& ScrollPosState
)
978 GetPropertyGrid()->GetViewStart(&x
,&y
);
979 result
+= wxString::Format(wxS("scrollpos=%i,%i;"), x
, y
);
981 if ( includedStates
& SplitterPosState
)
983 result
+= wxS("splitterpos=");
985 for ( size_t i
=0; i
<pageState
->GetColumnCount(); i
++ )
986 result
+= wxString::Format(wxS("%i,"), pageState
->DoGetSplitterPosition(i
));
988 result
.RemoveLast(); // Remove last comma
991 if ( includedStates
& PageState
)
993 result
+= wxS("ispageselected=");
995 if ( GetPageState(-1) == pageState
)
1000 result
.RemoveLast(); // Remove last semicolon
1005 if ( result
.length() )
1006 result
.RemoveLast();
1011 bool wxPropertyGridInterface::RestoreEditableState( const wxString
& src
, int restoreStates
)
1013 wxPropertyGrid
* pg
= GetPropertyGrid();
1014 wxPGProperty
* newSelection
= NULL
;
1018 long selectedPage
= -1;
1019 bool pgSelectionSet
= false;
1023 wxArrayString pageStrings
= ::wxSplit(src
, wxS('|'), wxS('\\'));
1025 for ( pageIndex
=0; pageIndex
<pageStrings
.size(); pageIndex
++ )
1027 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
1031 wxArrayString kvpairStrings
= ::wxSplit(pageStrings
[pageIndex
], wxS(';'), wxS('\\'));
1033 for ( size_t i
=0; i
<kvpairStrings
.size(); i
++ )
1035 const wxString
& kvs
= kvpairStrings
[i
];
1036 int eq_pos
= kvs
.Find(wxS('='));
1037 if ( eq_pos
!= wxNOT_FOUND
)
1039 wxString key
= kvs
.substr(0, eq_pos
);
1040 wxString value
= kvs
.substr(eq_pos
+1);
1042 // Further split value by commas
1043 wxArrayString values
= ::wxSplit(value
, wxS(','), wxS('\\'));
1045 if ( key
== wxS("expanded") )
1047 if ( restoreStates
& ExpandedState
)
1049 wxPropertyGridIterator it
=
1050 wxPropertyGridIterator( pageState
,
1054 // First collapse all
1055 for ( ; !it
.AtEnd(); it
.Next() )
1057 wxPGProperty
* p
= it
.GetProperty();
1058 pageState
->DoCollapse(p
);
1061 // Then expand those which names are in values
1062 for ( size_t n
=0; n
<values
.size(); n
++ )
1064 const wxString
& name
= values
[n
];
1065 wxPGProperty
* prop
= GetPropertyByName(name
);
1067 pageState
->DoExpand(prop
);
1071 else if ( key
== wxS("scrollpos") )
1073 if ( restoreStates
& ScrollPosState
)
1075 if ( values
.size() == 2 )
1077 values
[0].ToLong(&vx
);
1078 values
[1].ToLong(&vy
);
1086 else if ( key
== wxS("splitterpos") )
1088 if ( restoreStates
& SplitterPosState
)
1090 for ( size_t n
=1; n
<values
.size(); n
++ )
1093 values
[n
].ToLong(&pos
);
1095 pageState
->DoSetSplitterPosition(pos
, n
);
1099 else if ( key
== wxS("selection") )
1101 if ( restoreStates
& SelectionState
)
1103 if ( values
.size() > 0 )
1105 if ( pageState
->IsDisplayed() )
1107 if ( values
[0].length() )
1108 newSelection
= GetPropertyByName(value
);
1109 pgSelectionSet
= true;
1113 if ( values
[0].length() )
1114 pageState
->SetSelection(GetPropertyByName(value
));
1116 pageState
->DoClearSelection();
1121 else if ( key
== wxS("ispageselected") )
1123 if ( restoreStates
& PageState
)
1126 if ( values
.size() == 1 && values
[0].ToLong(&pageSelStatus
) )
1128 if ( pageSelStatus
)
1129 selectedPage
= pageIndex
;
1146 // Force recalculation of virtual heights of all pages
1147 // (may be needed on unclean source string).
1149 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
1152 pageState
->VirtualHeightChanged();
1154 pageState
= GetPageState(pageIndex
);
1160 // Selection of visible grid page must be set after Thaw() call
1161 if ( pgSelectionSet
)
1164 pg
->SelectProperty(newSelection
);
1166 pg
->ClearSelection();
1169 if ( selectedPage
!= -1 )
1171 DoSelectPage(selectedPage
);