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(wxPGVariantDataPoint
, wxPoint
)
69 WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataSize
, wxSize
)
70 WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataArrayInt
, wxArrayInt
)
71 WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataLongLong
, wxLongLong
)
72 WX_PG_IMPLEMENT_VARIANT_DATA(wxPGVariantDataULongLong
, wxULongLong
)
74 WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA(wxPGVariantDataFont
, wxFont
)
76 wxObject
* wxPG_VariantToWxObject( const wxVariant
& variant
, wxClassInfo
* classInfo
)
78 if ( !variant
.IsValueKindOf(classInfo
) )
79 return (wxObject
*) NULL
;
81 wxVariantData
* vdata
= variant
.GetData();
83 wxPGVariantData
* pgvdata
= wxDynamicCastVariantData(vdata
, wxPGVariantData
);
85 return (wxObject
*) pgvdata
->GetValuePtr();
87 if ( wxPGIsVariantClassInfo(wxPGVariantDataGetClassInfo(vdata
), wxobject
) )
88 return variant
.GetWxObjectPtr();
90 return (wxObject
*) NULL
;
93 // -----------------------------------------------------------------------
95 // -----------------------------------------------------------------------
97 long wxPGVariantToInt( const wxVariant
& variant
, long defVal
)
99 if ( variant
.IsNull() )
102 if ( wxPGIsVariantType(variant
, long) )
103 return variant
.GetLong();
105 if ( wxPGIsVariantType(variant
, bool) )
106 return variant
.GetBool() ? 1 : 0;
108 if ( typeid(*variant
.GetData()) == typeid(wxPGVariantDataLongLong
) )
110 wxLongLong ll
= ((const wxPGVariantDataLongLong
&)variant
).GetValue();
111 if ( ll
>= LONG_MAX
)
113 else if ( ll
<= LONG_MIN
)
120 if ( wxPGIsVariantType(variant
, string
) )
121 variant
.GetString().ToLong(&l
, 0);
126 // -----------------------------------------------------------------------
128 bool wxPGVariantToLongLong( const wxVariant
& variant
, wxLongLong_t
* pResult
)
130 if ( variant
.IsNull() )
133 if ( wxPGIsVariantType(variant
, long) )
135 *pResult
= variant
.GetLong();
139 if ( typeid(*variant
.GetData()) == typeid(wxPGVariantDataLongLong
) )
141 *pResult
= ((const wxPGVariantDataLongLong
&)variant
).GetValue().GetValue();
148 // -----------------------------------------------------------------------
150 bool wxPGVariantToULongLong( const wxVariant
& variant
, wxULongLong_t
* pResult
)
152 if ( variant
.IsNull() )
155 if ( wxPGIsVariantType(variant
, long) )
157 *pResult
= (unsigned long)variant
.GetLong();
161 if ( typeid(*variant
.GetData()) == typeid(wxPGVariantDataULongLong
) )
163 *pResult
= ((const wxPGVariantDataULongLong
&)variant
).GetValue().GetValue();
170 // -----------------------------------------------------------------------
172 bool wxPGVariantToDouble( const wxVariant
& variant
, double* pResult
)
174 if ( variant
.IsNull() )
177 if ( wxPGIsVariantType(variant
, double) )
179 *pResult
= variant
.GetDouble();
183 if ( wxPGIsVariantType(variant
, long) )
185 *pResult
= (double)variant
.GetLong();
189 if ( typeid(*variant
.GetData()) == typeid(wxPGVariantDataLongLong
) )
191 wxLongLong ll
= ((const wxPGVariantDataLongLong
&)variant
).GetValue();
192 *pResult
= ll
.ToDouble();
196 if ( wxPGIsVariantType(variant
, string
) )
197 if ( variant
.GetString().ToDouble(pResult
) )
203 // -----------------------------------------------------------------------
205 // -----------------------------------------------------------------------
207 wxPGProperty
* wxPGPropArgCls::GetPtr( wxPropertyGridInterface
* iface
) const
209 if ( m_flags
== IsProperty
)
211 wxASSERT_MSG( m_ptr
.property
, wxT("invalid property ptr") );
212 return m_ptr
.property
;
214 else if ( m_flags
& IsWxString
)
215 return iface
->GetPropertyByNameA(*m_ptr
.stringName
);
216 else if ( m_flags
& IsCharPtr
)
217 return iface
->GetPropertyByNameA(m_ptr
.charName
);
219 else if ( m_flags
& IsWCharPtr
)
220 return iface
->GetPropertyByNameA(m_ptr
.wcharName
);
226 // -----------------------------------------------------------------------
227 // Choice related methods
228 // -----------------------------------------------------------------------
230 void wxPropertyGridInterface::AddPropertyChoice( wxPGPropArg id
,
231 const wxString
& label
,
234 wxPG_PROP_ARG_CALL_PROLOG()
236 p
->InsertChoice(label
,-1,value
);
240 void wxPropertyGridInterface::InsertPropertyChoice( wxPGPropArg id
,
241 const wxString
& label
,
245 wxPG_PROP_ARG_CALL_PROLOG()
247 p
->InsertChoice(label
,index
,value
);
251 void wxPropertyGridInterface::DeletePropertyChoice( wxPGPropArg id
,
254 wxPG_PROP_ARG_CALL_PROLOG()
256 p
->DeleteChoice(index
);
259 // -----------------------------------------------------------------------
261 void wxPropertyGridInterface::RefreshGrid( wxPropertyGridPageState
* state
)
266 wxPropertyGrid
* grid
= state
->GetGrid();
267 if ( grid
->GetState() == state
&& !grid
->IsFrozen() )
273 // -----------------------------------------------------------------------
275 wxPGProperty
* wxPropertyGridInterface::Append( wxPGProperty
* property
)
277 wxPGProperty
* retp
= m_pState
->DoAppend(property
);
279 wxPropertyGrid
* grid
= m_pState
->GetGrid();
286 // -----------------------------------------------------------------------
288 wxPGProperty
* wxPropertyGridInterface::AppendIn( wxPGPropArg id
, wxPGProperty
* newproperty
)
290 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
291 wxPGProperty
* pwc
= (wxPGProperty
*) p
;
292 wxPGProperty
* retp
= m_pState
->DoInsert(pwc
, pwc
->GetChildCount(), newproperty
);
296 // -----------------------------------------------------------------------
298 wxPGProperty
* wxPropertyGridInterface::Insert( wxPGPropArg id
, wxPGProperty
* property
)
300 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
301 wxPGProperty
* retp
= m_pState
->DoInsert(p
->GetParent(), p
->GetArrIndex(), property
);
306 // -----------------------------------------------------------------------
308 wxPGProperty
* wxPropertyGridInterface::Insert( wxPGPropArg id
, int index
, wxPGProperty
* newproperty
)
310 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
311 wxPGProperty
* retp
= m_pState
->DoInsert((wxPGProperty
*)p
,index
,newproperty
);
316 // -----------------------------------------------------------------------
318 void wxPropertyGridInterface::DeleteProperty( wxPGPropArg id
)
320 wxPG_PROP_ARG_CALL_PROLOG()
322 wxPropertyGridPageState
* state
= p
->GetParentState();
323 wxPropertyGrid
* grid
= state
->GetGrid();
325 if ( grid
->GetState() == state
)
327 bool selRes
= grid
->DoSelectProperty(NULL
, wxPG_SEL_DELETING
);
328 wxPG_CHECK_RET_DBG( selRes
,
329 wxT("failed to deselect a property (editor probably had invalid value)") );
332 state
->DoDelete( p
);
337 // -----------------------------------------------------------------------
339 wxPGProperty
* wxPropertyGridInterface::ReplaceProperty( wxPGPropArg id
, wxPGProperty
* property
)
341 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty
)
343 wxPGProperty
* replaced
= p
;
344 wxCHECK_MSG( replaced
&& property
,
346 wxT("NULL property") );
347 wxCHECK_MSG( !replaced
->IsCategory(),
349 wxT("cannot replace this type of property") );
350 wxCHECK_MSG( !m_pState
->IsInNonCatMode(),
352 wxT("cannot replace properties in alphabetic mode") );
354 // Get address to the slot
355 wxPGProperty
* parent
= replaced
->GetParent();
356 int ind
= replaced
->GetIndexInParent();
358 wxPropertyGridPageState
* state
= replaced
->GetParentState();
359 DeleteProperty(replaced
); // Must use generic Delete
360 state
->DoInsert(parent
,ind
,property
);
365 // -----------------------------------------------------------------------
366 // wxPropertyGridInterface property operations
367 // -----------------------------------------------------------------------
369 bool wxPropertyGridInterface::ClearSelection()
371 wxPropertyGridPageState
* state
= m_pState
;
372 wxPropertyGrid
* pg
= state
->GetGrid();
373 if ( pg
->GetState() == state
)
374 return pg
->DoClearSelection();
376 state
->SetSelection(NULL
);
380 // -----------------------------------------------------------------------
382 void wxPropertyGridInterface::LimitPropertyEditing( wxPGPropArg id
, bool limit
)
384 wxPG_PROP_ARG_CALL_PROLOG()
386 m_pState
->DoLimitPropertyEditing(p
, limit
);
390 // -----------------------------------------------------------------------
392 bool wxPropertyGridInterface::EnableProperty( wxPGPropArg id
, bool enable
)
394 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
396 wxPropertyGridPageState
* state
= p
->GetParentState();
397 wxPropertyGrid
* grid
= state
->GetGrid();
401 if ( !(p
->m_flags
& wxPG_PROP_DISABLED
) )
404 // If active, Set active Editor.
405 if ( grid
->GetState() == state
&& p
== grid
->GetSelection() )
406 grid
->DoSelectProperty( p
, wxPG_SEL_FORCE
);
410 if ( p
->m_flags
& wxPG_PROP_DISABLED
)
413 // If active, Disable as active Editor.
414 if ( grid
->GetState() == state
&& p
== grid
->GetSelection() )
415 grid
->DoSelectProperty( p
, wxPG_SEL_FORCE
);
418 state
->DoEnableProperty(p
, enable
);
420 RefreshProperty( p
);
425 // -----------------------------------------------------------------------
427 bool wxPropertyGridInterface::ExpandAll( bool doExpand
)
429 wxPropertyGridPageState
* state
= m_pState
;
431 if ( !state
->DoGetRoot()->GetChildCount() )
434 wxPropertyGrid
* pg
= state
->GetGrid();
436 if ( GetSelection() && GetSelection() != state
->DoGetRoot() &&
439 if ( !pg
->ClearSelection() )
445 for ( it
= GetVIterator( wxPG_ITERATE_ALL
); !it
.AtEnd(); it
.Next() )
447 wxPGProperty
* p
= (wxPGProperty
*) it
.GetProperty();
448 if ( p
->GetChildCount() )
452 if ( !p
->IsExpanded() )
459 if ( p
->IsExpanded() )
461 state
->DoCollapse(p
);
467 pg
->RecalculateVirtualSize();
474 // -----------------------------------------------------------------------
476 void wxPropertyGridInterface::SetPropertyValueUnspecified( wxPGPropArg id
)
478 wxPG_PROP_ARG_CALL_PROLOG()
479 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
481 propGrid
->DoSetPropertyValueUnspecified(p
);
483 p
->GetParentState()->DoSetPropertyValueUnspecified(p
);
486 // -----------------------------------------------------------------------
487 // wxPropertyGridInterface property value setting and getting
488 // -----------------------------------------------------------------------
490 void wxPGGetFailed( const wxPGProperty
* p
, const wxChar
* typestr
)
492 wxPGTypeOperationFailed(p
,typestr
,wxT("Get"));
495 // -----------------------------------------------------------------------
497 void wxPGTypeOperationFailed( const wxPGProperty
* p
, const wxChar
* typestr
,
500 wxASSERT( p
!= NULL
);
501 wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."),
502 op
,p
->GetLabel().c_str(),p
->GetValue().GetType().c_str(),typestr
);
505 // -----------------------------------------------------------------------
507 void wxPropertyGridInterface::SetPropVal( wxPGPropArg id
, wxVariant
& value
)
509 wxPG_PROP_ARG_CALL_PROLOG()
514 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
516 propGrid
->DrawItemAndValueRelated( p
);
521 // -----------------------------------------------------------------------
523 void wxPropertyGridInterface::SetPropertyValueString( wxPGPropArg id
, const wxString
& value
)
525 wxPG_PROP_ARG_CALL_PROLOG()
527 if ( m_pState
->DoSetPropertyValueString(p
,value
) )
529 wxPropertyGrid
* propGrid
= p
->GetGridIfDisplayed();
531 propGrid
->DrawItemAndValueRelated( p
);
535 // -----------------------------------------------------------------------
537 void wxPropertyGridInterface::SetValidationFailureBehavior( int vfbFlags
)
539 GetPropertyGrid()->m_permanentValidationFailureBehavior
= vfbFlags
;
542 // -----------------------------------------------------------------------
544 wxPGProperty
* wxPropertyGridInterface::GetPropertyByNameA( const wxString
& name
) const
546 wxPGProperty
* p
= GetPropertyByName(name
);
547 wxASSERT_MSG(p
,wxString::Format(wxT("no property with name '%s'"),name
.c_str()));
551 // ----------------------------------------------------------------------------
553 wxPGProperty
* wxPropertyGridInterface::GetPropertyByLabel( const wxString
& label
) const
557 for ( it
= GetVIterator( wxPG_ITERATE_PROPERTIES
); !it
.AtEnd(); it
.Next() )
559 if ( it
.GetProperty()->GetLabel() == label
)
560 return it
.GetProperty();
563 return wxNullProperty
;
566 // ----------------------------------------------------------------------------
568 void wxPropertyGridInterface::DoSetPropertyAttribute( wxPGPropArg id
, const wxString
& name
,
569 wxVariant
& value
, long argFlags
)
571 wxPG_PROP_ARG_CALL_PROLOG()
573 p
->SetAttribute( name
, value
);
575 if ( argFlags
& wxPG_RECURSE
)
578 for ( i
= 0; i
< p
->GetChildCount(); i
++ )
579 DoSetPropertyAttribute(p
->Item(i
), name
, value
, argFlags
);
583 // -----------------------------------------------------------------------
585 void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty
* targetArr
,
586 wxPGProperty::FlagType flags
,
588 int iterFlags
) const
590 wxASSERT( targetArr
);
591 wxPGVIterator it
= GetVIterator( iterFlags
);
597 const wxPGProperty
* property
= it
.GetProperty();
601 if ( (property
->GetFlags() & flags
) == flags
)
602 targetArr
->push_back((wxPGProperty
*)property
);
606 if ( (property
->GetFlags() & flags
) != flags
)
607 targetArr
->push_back((wxPGProperty
*)property
);
612 // -----------------------------------------------------------------------
614 void wxPropertyGridInterface::SetPropertiesFlag( const wxArrayPGProperty
& srcArr
,
615 wxPGProperty::FlagType flags
,
620 for ( i
=0; i
<srcArr
.size(); i
++ )
622 wxPGProperty
* property
= srcArr
[i
];
625 property
->SetFlag(flags
);
627 property
->ClearFlag(flags
);
630 // If collapsed flag or hidden was manipulated, we need to update virtual
632 wxPropertyGrid
* pg
= GetPropertyGrid();
633 if ( flags
& (wxPG_PROP_COLLAPSED
|wxPG_PROP_HIDDEN
) )
635 GetState()->VirtualHeightChanged();
636 pg
->RecalculateVirtualSize();
640 // -----------------------------------------------------------------------
642 void wxPropertyGridInterface::SetBoolChoices( const wxString
& trueChoice
,
643 const wxString
& falseChoice
)
645 wxPGGlobalVars
->m_boolChoices
[0] = falseChoice
;
646 wxPGGlobalVars
->m_boolChoices
[1] = trueChoice
;
649 // -----------------------------------------------------------------------
651 wxPGChoices gs_emptyChoices
;
653 wxPGChoices
& wxPropertyGridInterface::GetPropertyChoices( wxPGPropArg id
)
655 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(gs_emptyChoices
)
658 ci
.m_choices
= (wxPGChoices
*) NULL
;
660 p
->GetChoiceInfo(&ci
);
663 return gs_emptyChoices
;
665 return *ci
.m_choices
;
668 // -----------------------------------------------------------------------
670 wxPGProperty
* wxPropertyGridInterface::DoGetPropertyByName( const wxString
& name
) const
672 return m_pState
->BaseGetPropertyByName(name
);
675 // -----------------------------------------------------------------------
677 wxPGProperty
* wxPropertyGridInterface::GetPropertyByName( const wxString
& name
,
678 const wxString
& subname
) const
680 wxPGProperty
* p
= DoGetPropertyByName(name
);
681 if ( !p
|| !p
->GetChildCount() )
682 return wxNullProperty
;
684 return p
->GetPropertyByName(subname
);
687 // -----------------------------------------------------------------------
689 // Since GetPropertyByName is used *a lot*, this makes sense
690 // since non-virtual method can be called with less code.
691 wxPGProperty
* wxPropertyGridInterface::GetPropertyByName( const wxString
& name
) const
693 wxPGProperty
* p
= DoGetPropertyByName(name
);
697 // Check if its "Property.SubProperty" format
698 int pos
= name
.Find(wxT('.'));
702 return GetPropertyByName(name
.substr(0,pos
),
703 name
.substr(pos
+1,name
.length()-pos
-1));
706 // -----------------------------------------------------------------------
708 bool wxPropertyGridInterface::HideProperty( wxPGPropArg id
, bool hide
, int flags
)
710 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
712 wxPropertyGrid
* pg
= m_pState
->GetGrid();
714 if ( pg
== p
->GetGrid() )
715 return pg
->DoHideProperty(p
, hide
, flags
);
717 m_pState
->DoHideProperty(p
, hide
, flags
);
722 // -----------------------------------------------------------------------
724 bool wxPropertyGridInterface::Collapse( wxPGPropArg id
)
726 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
727 wxPropertyGrid
* pg
= p
->GetGridIfDisplayed();
729 return pg
->DoCollapse(p
);
731 return p
->GetParentState()->DoCollapse(p
);
734 // -----------------------------------------------------------------------
736 bool wxPropertyGridInterface::Expand( wxPGPropArg id
)
738 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
739 wxPropertyGrid
* pg
= p
->GetGridIfDisplayed();
741 return pg
->DoExpand(p
);
743 return p
->GetParentState()->DoExpand(p
);
746 // -----------------------------------------------------------------------
748 void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id
, const wxString
& newproplabel
)
750 wxPG_PROP_ARG_CALL_PROLOG()
752 p
->SetLabel( newproplabel
);
754 wxPropertyGridPageState
* state
= p
->GetParentState();
755 wxPropertyGrid
* pg
= state
->GetGrid();
757 if ( pg
->HasFlag(wxPG_AUTO_SORT
) )
758 pg
->SortChildren(p
->GetParent());
760 if ( pg
->GetState() == state
)
762 if ( pg
->HasFlag(wxPG_AUTO_SORT
) )
769 // -----------------------------------------------------------------------
771 bool wxPropertyGridInterface::SetPropertyMaxLength( wxPGPropArg id
, int maxLen
)
773 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
775 wxPropertyGrid
* pg
= m_pState
->GetGrid();
777 p
->m_maxLen
= (short) maxLen
;
779 // Adjust control if selected currently
780 if ( pg
== p
->GetGrid() && p
== m_pState
->GetSelection() )
782 wxWindow
* wnd
= pg
->GetEditorControl();
783 wxTextCtrl
* tc
= wxDynamicCast(wnd
,wxTextCtrl
);
785 tc
->SetMaxLength( maxLen
);
794 // -----------------------------------------------------------------------
795 // GetPropertyValueAsXXX methods
797 #define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \
798 TRET wxPropertyGridInterface::GetPropertyValueAs##BIGNAME( wxPGPropArg id ) const \
800 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFRETVAL) \
801 wxVariant value = p->GetValue(); \
802 if ( wxStrcmp(value.GetType(), wxPGTypeName_##T) != 0 ) \
804 wxPGGetFailed(p,wxPGTypeName_##T); \
805 return (TRET)DEFRETVAL; \
807 return (TRET)value.Get##BIGNAME(); \
810 // String is different than others.
811 wxString
wxPropertyGridInterface::GetPropertyValueAsString( wxPGPropArg id
) const
813 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxEmptyString
)
814 return p
->GetValueAsString(wxPG_FULL_VALUE
);
817 bool wxPropertyGridInterface::GetPropertyValueAsBool( wxPGPropArg id
) const
819 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
820 wxVariant value
= p
->GetValue();
821 if ( wxStrcmp(value
.GetType(), wxPGTypeName_bool
) == 0 )
823 return value
.GetBool();
825 if ( wxStrcmp(value
.GetType(), wxPGTypeName_long
) == 0 )
827 return value
.GetLong()?true:false;
829 wxPGGetFailed(p
,wxPGTypeName_bool
);
833 IMPLEMENT_GET_VALUE(long,long,Long
,0)
834 IMPLEMENT_GET_VALUE(double,double,Double
,0.0)
835 IMPLEMENT_GET_VALUE(void,void*,VoidPtr
,NULL
)
837 // wxObject is different than others.
838 wxObject
* wxPropertyGridInterface::GetPropertyValueAsWxObjectPtr( wxPGPropArg id
) const
840 wxPG_PROP_ARG_CALL_PROLOG_RETVAL((wxObject
*)NULL
)
842 wxVariant value
= p
->GetValue();
843 wxVariantData
* vdata
= value
.GetData();
845 if ( !vdata
->GetValueClassInfo() )
846 return (wxObject
*) NULL
;
848 wxPGVariantData
* pgvdata
= wxDynamicCastVariantData(vdata
, wxPGVariantData
);
850 return (wxObject
*) pgvdata
->GetValuePtr();
852 if ( wxPGIsVariantClassInfo(wxPGVariantDataGetClassInfo(vdata
), wxobject
) )
853 return (wxObject
*) value
.GetWxObjectPtr();
855 return (wxObject
*) NULL
;
858 // -----------------------------------------------------------------------
860 bool wxPropertyGridInterface::IsPropertyExpanded( wxPGPropArg id
) const
862 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
863 return p
->IsExpanded();
866 // -----------------------------------------------------------------------
867 // wxPropertyGridInterface wrappers
868 // -----------------------------------------------------------------------
870 bool wxPropertyGridInterface::ChangePropertyValue( wxPGPropArg id
, wxVariant newValue
)
872 return GetPropertyGrid()->ChangePropertyValue(id
, newValue
);
875 // -----------------------------------------------------------------------
877 void wxPropertyGridInterface::BeginAddChildren( wxPGPropArg id
)
879 wxPG_PROP_ARG_CALL_PROLOG()
880 wxCHECK_RET( p
->HasFlag(wxPG_PROP_AGGREGATE
), wxT("only call on properties with fixed children") );
881 p
->ClearFlag(wxPG_PROP_AGGREGATE
);
882 p
->SetFlag(wxPG_PROP_MISC_PARENT
);
885 // -----------------------------------------------------------------------
887 bool wxPropertyGridInterface::EditorValidate()
889 return GetPropertyGrid()->DoEditorValidate();
892 // -----------------------------------------------------------------------
894 void wxPropertyGridInterface::EndAddChildren( wxPGPropArg id
)
896 wxPG_PROP_ARG_CALL_PROLOG()
897 wxCHECK_RET( p
->HasFlag(wxPG_PROP_MISC_PARENT
), wxT("only call on properties for which BeginAddChildren was called prior") );
898 p
->ClearFlag(wxPG_PROP_MISC_PARENT
);
899 p
->SetFlag(wxPG_PROP_AGGREGATE
);
902 // -----------------------------------------------------------------------
903 // wxPGVIterator_State
904 // -----------------------------------------------------------------------
906 // Default returned by wxPropertyGridInterface::GetVIterator().
907 class wxPGVIteratorBase_State
: public wxPGVIteratorBase
910 wxPGVIteratorBase_State( wxPropertyGridPageState
* state
, int flags
)
912 m_it
.Init( state
, flags
);
914 virtual ~wxPGVIteratorBase_State() { }
915 virtual void Next() { m_it
.Next(); }
918 wxPGVIterator
wxPropertyGridInterface::GetVIterator( int flags
) const
920 return wxPGVIterator( new wxPGVIteratorBase_State( m_pState
, flags
) );
923 // -----------------------------------------------------------------------
924 // wxPGEditableState related functions
925 // -----------------------------------------------------------------------
927 // EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
928 // in the input string. This is an internal functions which is
929 // used for saving states
930 // NB: Similar function exists in aui/framemanager.cpp
931 static wxString
EscapeDelimiters(const wxString
& s
)
934 result
.Alloc(s
.length());
935 const wxChar
* ch
= s
.c_str();
938 if (*ch
== wxT(';') || *ch
== wxT('|') || *ch
== wxT(','))
946 wxString
wxPropertyGridInterface::SaveEditableState( int includedStates
) const
951 // Save state on page basis
952 size_t pageIndex
= 0;
953 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
954 wxArrayPtrVoid pageStates
;
957 pageStates
.Add(pageState
);
959 pageState
= GetPageState(pageIndex
);
962 for ( pageIndex
=0; pageIndex
< pageStates
.size(); pageIndex
++ )
964 wxPropertyGridPageState
* pageState
= (wxPropertyGridPageState
*) pageStates
[pageIndex
];
966 if ( includedStates
& SelectionState
)
969 if ( pageState
->GetSelection() )
970 sel
= pageState
->GetSelection()->GetName();
971 result
+= wxS("selection=");
972 result
+= EscapeDelimiters(sel
);
975 if ( includedStates
& ExpandedState
)
977 wxArrayPGProperty ptrs
;
978 wxPropertyGridConstIterator it
=
979 wxPropertyGridConstIterator( pageState
,
980 wxPG_ITERATE_ALL_PARENTS_RECURSIVELY
|wxPG_ITERATE_HIDDEN
,
983 result
+= wxS("expanded=");
989 const wxPGProperty
* p
= it
.GetProperty();
991 if ( !p
->HasFlag(wxPG_PROP_COLLAPSED
) )
992 result
+= EscapeDelimiters(p
->GetName());
997 if ( result
.Last() == wxS(',') )
1002 if ( includedStates
& ScrollPosState
)
1005 GetPropertyGrid()->GetViewStart(&x
,&y
);
1006 result
+= wxString::Format(wxS("scrollpos=%i,%i;"), x
, y
);
1008 if ( includedStates
& SplitterPosState
)
1010 result
+= wxS("splitterpos=");
1012 for ( size_t i
=0; i
<pageState
->GetColumnCount(); i
++ )
1013 result
+= wxString::Format(wxS("%i,"), pageState
->DoGetSplitterPosition(i
));
1015 result
.RemoveLast(); // Remove last comma
1018 if ( includedStates
& PageState
)
1020 result
+= wxS("ispageselected=");
1022 if ( GetPageState(-1) == pageState
)
1023 result
+= wxS("1;");
1025 result
+= wxS("0;");
1027 result
.RemoveLast(); // Remove last semicolon
1032 if ( result
.length() )
1033 result
.RemoveLast();
1038 bool wxPropertyGridInterface::RestoreEditableState( const wxString
& src
, int restoreStates
)
1040 wxPropertyGrid
* pg
= GetPropertyGrid();
1041 wxPGProperty
* newSelection
= NULL
;
1045 long selectedPage
= -1;
1046 bool pgSelectionSet
= false;
1050 wxArrayString pageStrings
= ::wxSplit(src
, wxS('|'), wxS('\\'));
1052 for ( pageIndex
=0; pageIndex
<pageStrings
.size(); pageIndex
++ )
1054 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
1058 wxArrayString kvpairStrings
= ::wxSplit(pageStrings
[pageIndex
], wxS(';'), wxS('\\'));
1060 for ( size_t i
=0; i
<kvpairStrings
.size(); i
++ )
1062 const wxString
& kvs
= kvpairStrings
[i
];
1063 int eq_pos
= kvs
.Find(wxS('='));
1064 if ( eq_pos
!= wxNOT_FOUND
)
1066 wxString key
= kvs
.substr(0, eq_pos
);
1067 wxString value
= kvs
.substr(eq_pos
+1);
1069 // Further split value by commas
1070 wxArrayString values
= ::wxSplit(value
, wxS(','), wxS('\\'));
1072 if ( key
== wxS("expanded") )
1074 if ( restoreStates
& ExpandedState
)
1076 wxPropertyGridIterator it
=
1077 wxPropertyGridIterator( pageState
,
1081 // First collapse all
1082 for ( ; !it
.AtEnd(); it
.Next() )
1084 wxPGProperty
* p
= it
.GetProperty();
1085 pageState
->DoCollapse(p
);
1088 // Then expand those which names are in values
1089 for ( size_t n
=0; n
<values
.size(); n
++ )
1091 const wxString
& name
= values
[n
];
1092 wxPGProperty
* prop
= GetPropertyByName(name
);
1094 pageState
->DoExpand(prop
);
1098 else if ( key
== wxS("scrollpos") )
1100 if ( restoreStates
& ScrollPosState
)
1102 if ( values
.size() == 2 )
1104 values
[0].ToLong(&vx
);
1105 values
[1].ToLong(&vy
);
1113 else if ( key
== wxS("splitterpos") )
1115 if ( restoreStates
& SplitterPosState
)
1117 for ( size_t n
=1; n
<values
.size(); n
++ )
1120 values
[n
].ToLong(&pos
);
1122 pageState
->DoSetSplitterPosition(pos
, n
);
1126 else if ( key
== wxS("selection") )
1128 if ( restoreStates
& SelectionState
)
1130 if ( values
.size() > 0 )
1132 if ( pageState
->IsDisplayed() )
1134 if ( values
[0].length() )
1135 newSelection
= GetPropertyByName(value
);
1136 pgSelectionSet
= true;
1140 if ( values
[0].length() )
1141 pageState
->SetSelection(GetPropertyByName(value
));
1143 pageState
->DoClearSelection();
1148 else if ( key
== wxS("ispageselected") )
1150 if ( restoreStates
& PageState
)
1153 if ( values
.size() == 1 && values
[0].ToLong(&pageSelStatus
) )
1155 if ( pageSelStatus
)
1156 selectedPage
= pageIndex
;
1173 // Force recalculation of virtual heights of all pages
1174 // (may be needed on unclean source string).
1176 wxPropertyGridPageState
* pageState
= GetPageState(pageIndex
);
1179 pageState
->VirtualHeightChanged();
1181 pageState
= GetPageState(pageIndex
);
1187 // Selection of visible grid page must be set after Thaw() call
1188 if ( pgSelectionSet
)
1191 pg
->SelectProperty(newSelection
);
1193 pg
->ClearSelection();
1196 if ( selectedPage
!= -1 )
1198 DoSelectPage(selectedPage
);