1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/property.cpp
3 // Purpose: wxPGProperty and related support classes
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/propgrid.h>
53 #define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's
56 #define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing
59 // -----------------------------------------------------------------------
61 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect
)
63 #if defined(__WXMSW__) && !defined(__WXWINCE__)
64 // FIXME: Use DrawFocusRect code above (currently it draws solid line
65 // for caption focus but works ok for other stuff).
66 // Also, it seems that this code may not work in future wx versions.
67 dc
.SetLogicalFunction(wxINVERT
);
69 wxPen
pen(*wxBLACK
,1,wxDOT
);
70 pen
.SetCap(wxCAP_BUTT
);
72 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
74 dc
.DrawRectangle(rect
);
76 dc
.SetLogicalFunction(wxCOPY
);
78 dc
.SetLogicalFunction(wxINVERT
);
80 dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
));
81 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
83 dc
.DrawRectangle(rect
);
85 dc
.SetLogicalFunction(wxCOPY
);
89 // -----------------------------------------------------------------------
91 // -----------------------------------------------------------------------
93 wxSize
wxPGCellRenderer::GetImageSize( const wxPGProperty
* WXUNUSED(property
),
95 int WXUNUSED(item
) ) const
100 void wxPGCellRenderer::DrawText( wxDC
& dc
, const wxRect
& rect
,
101 int xOffset
, const wxString
& text
) const
104 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
106 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
107 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
110 void wxPGCellRenderer::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
111 int xOffset
, const wxString
& text
,
112 wxPGProperty
* property
,
113 const wxPGEditor
* editor
) const
116 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
118 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
125 rect2
.height
-= yOffset
;
126 editor
->DrawValue( dc
, rect2
, property
, text
);
131 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
136 void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
138 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
139 wxPGDrawFocusRect(dc
,focusRect
);
142 int wxPGCellRenderer::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
146 if ( !(flags
& Selected
) )
148 // Draw using wxPGCell information, if available
149 wxColour fgCol
= cell
.GetFgCol();
151 dc
.SetTextForeground(fgCol
);
153 wxColour bgCol
= cell
.GetBgCol();
158 dc
.DrawRectangle(rect
);
162 const wxBitmap
& bmp
= cell
.GetBitmap();
164 // In control, do not draw oversized bitmap
165 (!(flags
& Control
) || bmp
.GetHeight() < rect
.height
)
169 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
170 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
172 imageOffset
= bmp
.GetWidth();
178 // -----------------------------------------------------------------------
179 // wxPGDefaultRenderer
180 // -----------------------------------------------------------------------
182 void wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
,
183 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
184 int column
, int item
, int flags
) const
186 bool isUnspecified
= property
->IsValueUnspecified();
188 if ( column
== 1 && item
== -1 )
190 int cmnVal
= property
->GetCommonValue();
194 if ( !isUnspecified
)
195 DrawText( dc
, rect
, 0, propertyGrid
->GetCommonValueLabel(cmnVal
) );
200 const wxPGEditor
* editor
= NULL
;
201 const wxPGCell
* cell
= property
->GetCell(column
);
207 if ( column
== 1 && (flags
& Control
) )
209 const wxPGCell
* ccell
= property
->GetCurrentChoice();
211 ( ccell
->GetBitmap().IsOk() || ccell
->GetFgCol().IsOk() || ccell
->GetBgCol().IsOk() )
218 int preDrawFlags
= flags
;
220 if ( propertyGrid
->GetInternalFlags() & wxPG_FL_CELL_OVERRIDES_SEL
)
221 preDrawFlags
= preDrawFlags
& ~(Selected
);
223 imageOffset
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
224 text
= cell
->GetText();
225 if ( text
== wxS("@!") )
228 text
= property
->GetLabel();
229 else if ( column
== 1 )
230 text
= property
->GetValueString();
232 text
= wxEmptyString
;
235 else if ( column
== 0 )
238 DrawText( dc
, rect
, 0, property
->GetLabel() );
240 else if ( column
== 1 )
242 if ( !isUnspecified
)
244 editor
= property
->GetColumnEditor(column
);
246 // Regular property value
248 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
250 wxPGPaintData paintdata
;
251 paintdata
.m_parent
= propertyGrid
;
252 paintdata
.m_choiceItem
= item
;
254 if ( imageSize
.x
> 0 )
256 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
257 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
258 wxPG_CUSTOM_IMAGE_WIDTH
,
259 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
261 /*if ( imageSize.x == wxPG_FULL_CUSTOM_PAINT_WIDTH )
263 imageRect.width = m_width - imageRect.x;
266 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
268 paintdata
.m_drawnWidth
= imageSize
.x
;
269 paintdata
.m_drawnHeight
= imageSize
.y
;
271 if ( !isUnspecified
)
273 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
277 dc
.SetBrush(*wxWHITE_BRUSH
);
278 dc
.DrawRectangle(imageRect
);
281 imageOffset
= paintdata
.m_drawnWidth
;
284 text
= property
->GetValueString();
287 if ( propertyGrid
->GetColumnCount() <= 2 )
289 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
290 if ( unitsString
.length() )
291 text
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
295 if ( text
.length() == 0 )
297 // Try to show inline help if no text
298 wxVariant vInlineHelp
= property
->GetAttribute(wxPGGlobalVars
->m_strInlineHelp
);
299 if ( !vInlineHelp
.IsNull() )
301 text
= vInlineHelp
.GetString();
302 dc
.SetTextForeground(propertyGrid
->GetCellDisabledTextColour());
306 else if ( column
== 2 )
309 if ( !text
.length() )
310 text
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
313 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
315 // active caption gets nice dotted rectangle
316 if ( property
->IsCategory() /*&& column == 0*/ )
318 if ( flags
& Selected
)
320 if ( imageOffset
> 0 )
321 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
323 DrawCaptionSelectionRect( dc
,
324 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
325 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
326 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
327 propertyGrid
->GetCaptionFont())
328 +(wxPG_CAPRECTXMARGIN
*2),
329 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
334 wxSize
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
,
338 if ( property
&& column
== 1 )
342 wxBitmap
* bmp
= property
->GetValueImage();
344 if ( bmp
&& bmp
->Ok() )
345 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
351 // -----------------------------------------------------------------------
353 // -----------------------------------------------------------------------
359 wxPGCell::wxPGCell( const wxString
& text
,
360 const wxBitmap
& bitmap
,
361 const wxColour
& fgCol
,
362 const wxColour
& bgCol
)
363 : m_bitmap(bitmap
), m_fgCol(fgCol
), m_bgCol(bgCol
)
368 // -----------------------------------------------------------------------
370 // -----------------------------------------------------------------------
372 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
374 wxString
* wxPGProperty::sm_wxPG_LABEL
= NULL
;
376 void wxPGProperty::Init()
382 m_parentState
= (wxPropertyGridPageState
*) NULL
;
385 m_clientObject
= NULL
;
387 m_customEditor
= (wxPGEditor
*) NULL
;
389 m_validator
= (wxValidator
*) NULL
;
391 m_valueBitmap
= (wxBitmap
*) NULL
;
393 m_maxLen
= 0; // infinite maximum length
395 m_flags
= wxPG_PROP_PROPERTY
;
405 void wxPGProperty::Init( const wxString
& label
, const wxString
& name
)
407 // We really need to check if &label and &name are NULL pointers
408 // (this can if we are called before property grid has been initalized)
410 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
413 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
416 DoSetName( m_label
);
421 wxPGProperty::wxPGProperty()
428 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name
)
435 wxPGProperty::~wxPGProperty()
437 delete m_clientObject
;
439 Empty(); // this deletes items
441 delete m_valueBitmap
;
448 for ( i
=0; i
<m_cells
.size(); i
++ )
449 delete (wxPGCell
*) m_cells
[i
];
451 // This makes it easier for us to detect dangling pointers
456 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate
) const
458 wxPGProperty
* parent
= m_parent
;
461 if ( parent
== candidate
)
463 parent
= parent
->m_parent
;
469 wxString
wxPGProperty::GetName() const
471 wxPGProperty
* parent
= GetParent();
473 if ( !m_name
.length() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
476 return m_parent
->GetName() + wxS(".") + m_name
;
479 wxPropertyGrid
* wxPGProperty::GetGrid() const
481 if ( !m_parentState
)
483 return m_parentState
->GetGrid();
487 void wxPGProperty::UpdateControl( wxWindow
* primary
)
490 GetEditorClass()->UpdateControl(this, primary
);
493 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
498 void wxPGProperty::OnSetValue()
502 void wxPGProperty::RefreshChildren ()
506 wxString
wxPGProperty::GetColumnText( unsigned int col
) const
508 wxPGCell
* cell
= GetCell(col
);
511 return cell
->GetText();
518 return GetDisplayedString();
520 return GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
523 return wxEmptyString
;
526 void wxPGProperty::GenerateComposedValue( wxString
& text
, int argFlags
) const
529 int iMax
= m_children
.GetCount();
535 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
536 !(argFlags
& wxPG_FULL_VALUE
) )
537 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
539 int iMaxMinusOne
= iMax
-1;
541 if ( !IsTextEditable() )
542 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
544 wxPGProperty
* curChild
= (wxPGProperty
*) m_children
.Item(0);
546 for ( i
= 0; i
< iMax
; i
++ )
549 if ( !curChild
->IsValueUnspecified() )
550 s
= curChild
->GetValueString(argFlags
|wxPG_COMPOSITE_FRAGMENT
);
553 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() )
556 if ( !curChild
->GetChildCount() || skip
)
559 text
+= wxS("[") + s
+ wxS("]");
561 if ( i
< iMaxMinusOne
)
563 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
564 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
565 !(argFlags
& wxPG_FULL_VALUE
) )
570 if ( !curChild
->GetChildCount() )
576 curChild
= (wxPGProperty
*) m_children
.Item(i
+1);
580 // Remove superfluous semicolon and space
582 if ( text
.EndsWith(wxS("; "), &rest
) )
585 if ( (unsigned int)i
< m_children
.GetCount() )
586 text
+= wxS("; ...");
589 wxString
wxPGProperty::GetValueAsString( int argFlags
) const
591 wxCHECK_MSG( GetChildCount() > 0,
593 wxT("If user property does not have any children, it must override GetValueAsString") );
596 GenerateComposedValue(text
, argFlags
);
600 wxString
wxPGProperty::GetValueString( int argFlags
) const
602 if ( IsValueUnspecified() )
603 return wxEmptyString
;
605 if ( m_commonValue
== -1 )
606 return GetValueAsString(argFlags
);
609 // Return common value's string representation
610 wxPropertyGrid
* pg
= GetGrid();
611 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
613 if ( argFlags
& wxPG_FULL_VALUE
)
615 return cv
->GetLabel();
617 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
619 return cv
->GetEditableText();
623 return cv
->GetLabel();
627 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
629 variant
= (long)number
;
633 // Convert semicolon delimited tokens into child values.
634 bool wxPGProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
636 if ( !GetChildCount() )
639 unsigned int curChild
= 0;
641 unsigned int iMax
= m_children
.GetCount();
643 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
644 !(argFlags
& wxPG_FULL_VALUE
) )
645 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
647 bool changed
= false;
652 // Its best only to add non-empty group items
653 bool addOnlyIfNotEmpty
= false;
654 const wxChar delimeter
= wxS(';');
656 size_t tokenStart
= 0xFFFFFF;
658 wxVariantList temp_list
;
659 wxVariant
list(temp_list
);
661 int propagatedFlags
= argFlags
& wxPG_REPORT_ERROR
;
664 bool debug_print
= false;
669 wxLogDebug(wxT(">> %s.StringToValue('%s')"),GetLabel().c_str(),text
.c_str());
672 wxString::const_iterator it
= text
.begin();
675 if ( it
!= text
.end() )
682 if ( tokenStart
!= 0xFFFFFF )
685 if ( a
== delimeter
|| a
== 0 )
687 token
= text
.substr(tokenStart
,pos
-tokenStart
);
689 size_t len
= token
.length();
691 if ( !addOnlyIfNotEmpty
|| len
> 0 )
693 const wxPGProperty
* child
= Item(curChild
);
696 wxLogDebug(wxT("token = '%s', child = %s"),token
.c_str(),child
->GetLabel().c_str());
701 bool wasUnspecified
= child
->IsValueUnspecified();
703 wxVariant
variant(child
->GetValueRef());
704 if ( child
->StringToValue(variant
, token
, propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
706 // Use label instead of name, as name can be empty string, but
707 // label in practice never is.
708 variant
.SetName(child
->GetLabel());
710 // Clear unspecified flag only if OnSetValue() didn't
712 if ( child
->IsValueUnspecified() &&
713 (wasUnspecified
|| !UsesAutoUnspecified()) )
715 variant
= child
->GetDefaultValue();
718 list
.Append(variant
);
725 // Empty, becomes unspecified
727 variant2
.SetName(child
->GetLabel());
728 list
.Append(variant2
);
733 if ( curChild
>= iMax
)
737 tokenStart
= 0xFFFFFF;
742 // Token is not running
746 addOnlyIfNotEmpty
= false;
748 // Is this a group of tokens?
753 if ( it
!= text
.end() ) it
++;
755 size_t startPos
= pos
;
757 // Group item - find end
758 while ( it
!= text
.end() && depth
> 0 )
766 else if ( a
== wxS('[') )
770 token
= text
.substr(startPos
,pos
-startPos
-1);
772 if ( !token
.length() )
775 const wxPGProperty
* child
= Item(curChild
);
777 wxVariant
variant(child
->GetValueRef());
778 if ( child
->StringToValue( variant
, token
, propagatedFlags
) )
780 // Use label instead of name, as name can be empty string, but
781 // label in practice never is.
782 variant
.SetName(child
->GetLabel());
783 list
.Append(variant
);
788 // Failed, becomes unspecified
790 variant2
.SetName(child
->GetLabel());
791 list
.Append(variant2
);
796 if ( curChild
>= iMax
)
799 addOnlyIfNotEmpty
= true;
801 tokenStart
= 0xFFFFFF;
807 if ( a
== delimeter
)
820 if ( it
!= text
.end() )
837 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags
)
839 wxVariant
variant(m_value
);
840 bool res
= StringToValue(variant
, text
, argFlags
);
846 bool wxPGProperty::SetValueFromInt( long number
, int argFlags
)
848 wxVariant
variant(m_value
);
849 bool res
= IntToValue(variant
, number
, argFlags
);
855 wxSize
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const
858 return wxSize(m_valueBitmap
->GetWidth(),-1);
863 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const
865 return wxPGGlobalVars
->m_defaultRenderer
;
868 void wxPGProperty::OnCustomPaint( wxDC
& dc
,
872 wxBitmap
* bmp
= m_valueBitmap
;
874 wxCHECK_RET( bmp
&& bmp
->Ok(), wxT("invalid bitmap") );
876 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
878 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
881 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const
883 return wxPG_EDITOR(TextCtrl
);
886 // Default extra property event handling - that is, none at all.
887 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
893 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
895 if ( !value
.IsNull() )
898 // List variants are reserved a special purpose
899 // as intermediate containers for child values
900 // of properties with children.
901 if ( wxPGIsVariantType(value
, list
) )
904 AdaptListToValue(value
, &newValue
);
906 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
909 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
910 flags
|= wxPG_SETVAL_AGGREGATED
;
912 if ( pList
&& !pList
->IsNull() )
914 wxASSERT( wxPGIsVariantType(*pList
, list
) );
915 wxASSERT( GetChildCount() );
916 wxASSERT( !IsCategory() );
918 wxVariantList
& list
= pList
->GetList();
919 wxVariantList::iterator node
;
922 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
924 // Children in list can be in any order, but we will give hint to
925 // GetPropertyByLabelWH(). This optimizes for full list parsing.
926 for ( node
= list
.begin(); node
!= list
.end(); node
++ )
928 wxVariant
& childValue
= *((wxVariant
*)*node
);
929 wxPGProperty
* child
= GetPropertyByLabelWH(childValue
.GetName(), i
);
932 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetLabel().c_str(),childValue.GetType().c_str());
933 if ( wxPGIsVariantType(childValue
, list
) )
935 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
937 wxVariant listRefCopy
= childValue
;
938 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
942 wxVariant oldVal
= child
->GetValue();
943 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
946 else if ( !wxPG_VARIANT_EQ(child
->GetValue(), childValue
) )
947 // This flag is not normally set when setting value programmatically.
948 // However, this loop is usually only executed when called from
949 // DoPropertyChanged, which should set this flag.
951 // For aggregate properties, we will trust RefreshChildren()
952 // to update child values.
953 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
954 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
955 child
->SetFlag(wxPG_PROP_MODIFIED
);
962 if ( !value
.IsNull() )
964 wxPGVariantAssign(m_value
, value
);
967 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
968 UpdateParentValues();
972 SetFlag(wxPG_PROP_MODIFIED
);
974 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
979 if ( m_commonValue
!= -1 )
981 wxPropertyGrid
* pg
= GetGrid();
982 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
988 // Set children to unspecified, but only if aggregate or
989 // value is <composed>
990 if ( AreChildrenComponents() )
993 for ( i
=0; i
<GetChildCount(); i
++ )
994 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
999 // Update editor control
1002 // We need to check for these, otherwise GetGrid() may fail.
1003 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1008 void wxPGProperty::SetValueInEvent( wxVariant value
) const
1010 GetGrid()->ValueChangeInEvent(value
);
1013 void wxPGProperty::SetFlagRecursively( FlagType flag
, bool set
)
1021 for ( i
= 0; i
< GetChildCount(); i
++ )
1022 Item(i
)->SetFlagRecursively(flag
, set
);
1025 void wxPGProperty::RefreshEditor()
1027 if ( m_parent
&& GetParentState() )
1029 wxPropertyGrid
* pg
= GetParentState()->GetGrid();
1030 if ( pg
->GetSelectedProperty() == this )
1032 wxWindow
* editor
= pg
->GetEditorControl();
1034 GetEditorClass()->UpdateControl( this, editor
);
1040 wxVariant
wxPGProperty::GetDefaultValue() const
1042 wxVariant defVal
= GetAttribute(wxS("DefaultValue"));
1043 if ( !defVal
.IsNull() )
1046 wxVariant value
= GetValue();
1048 if ( !value
.IsNull() )
1050 wxPGVariantDataClassInfo classInfo
= wxPGVariantDataGetClassInfo(value
.GetData());
1051 if ( wxPGIsVariantClassInfo(classInfo
, long) )
1052 return wxPGVariant_Zero
;
1053 if ( wxPGIsVariantClassInfo(classInfo
, string
) )
1054 return wxPGVariant_EmptyString
;
1055 if ( wxPGIsVariantClassInfo(classInfo
, bool) )
1056 return wxPGVariant_False
;
1057 if ( wxPGIsVariantClassInfo(classInfo
, double) )
1058 return wxVariant(0.0);
1060 wxPGVariantData
* pgvdata
= wxDynamicCastVariantData(m_value
.GetData(), wxPGVariantData
);
1062 return pgvdata
->GetDefaultValue();
1064 if ( wxPGIsVariantClassInfo(classInfo
, arrstring
) )
1065 return wxVariant(wxArrayString());
1066 if ( wxPGIsVariantClassInfo(classInfo
, wxColour
) )
1067 return WXVARIANT(*wxRED
);
1069 if ( wxPGIsVariantClassInfo(classInfo
, datetime
) )
1070 return wxVariant(wxDateTime::Now());
1074 wxString::Format(wxT("Inorder for value to have default value, it must be added to")
1075 wxT("wxPGProperty::GetDefaultValue or it's variantdata must inherit")
1076 wxT("from wxPGVariantData (unrecognized type was '%s')"),m_value
.GetType().c_str())
1083 void wxPGProperty::SetCell( int column
, wxPGCell
* cellObj
)
1085 if ( column
>= (int)m_cells
.size() )
1086 m_cells
.SetCount(column
+1, NULL
);
1088 delete (wxPGCell
*) m_cells
[column
];
1089 m_cells
[column
] = cellObj
;
1092 void wxPGProperty::SetChoiceSelection( int newValue
, const wxPGChoiceInfo
& choiceInfo
)
1094 // Changes value of a property with choices, but only
1095 // works if the value type is long or string.
1096 wxString ts
= GetValue().GetType();
1098 wxCHECK_RET( choiceInfo
.m_choices
, wxT("invalid choiceinfo") );
1100 if ( ts
== wxS("long") )
1102 SetValue( (long) newValue
);
1104 else if ( ts
== wxS("string") )
1106 SetValue( choiceInfo
.m_choices
->GetLabel(newValue
) );
1111 wxString
wxPGProperty::GetChoiceString( unsigned int index
)
1115 wxASSERT(ci
.m_choices
);
1116 return ci
.m_choices
->GetLabel(index
);
1119 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value
)
1121 wxPropertyGrid
* pg
= GetGrid();
1124 ci
.m_choices
= (wxPGChoices
*) NULL
;
1125 int sel
= GetChoiceInfo(&ci
);
1132 index
= ci
.m_choices
->GetCount();
1137 ci
.m_choices
->Insert(label
, index
, value
);
1139 if ( sel
!= newSel
)
1140 SetChoiceSelection(newSel
, ci
);
1142 if ( this == pg
->GetSelection() )
1143 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1152 void wxPGProperty::DeleteChoice( int index
)
1154 wxPropertyGrid
* pg
= GetGrid();
1157 ci
.m_choices
= (wxPGChoices
*) NULL
;
1158 int sel
= GetChoiceInfo(&ci
);
1164 // Adjust current value
1167 SetValueToUnspecified();
1170 else if ( index
< sel
)
1175 ci
.m_choices
->RemoveAt(index
);
1177 if ( sel
!= newSel
)
1178 SetChoiceSelection(newSel
, ci
);
1180 if ( this == pg
->GetSelection() )
1181 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1185 int wxPGProperty::GetChoiceInfo( wxPGChoiceInfo
* WXUNUSED(info
) )
1190 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const
1195 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1200 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value
)
1202 if ( DoSetAttribute( name
, value
) )
1204 // Support working without grid, when possible
1205 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1209 m_attributes
.Set( name
, value
);
1212 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes
)
1214 wxPGAttributeStorage::const_iterator it
= attributes
.StartIteration();
1217 while ( attributes
.GetNext(it
, variant
) )
1218 SetAttribute( variant
.GetName(), variant
);
1221 wxVariant
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1227 wxVariant
wxPGProperty::GetAttribute( const wxString
& name
) const
1229 return m_attributes
.FindValue(name
);
1232 wxString
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1234 wxVariant variant
= m_attributes
.FindValue(name
);
1236 if ( !variant
.IsNull() )
1237 return variant
.GetString();
1242 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1244 wxVariant variant
= m_attributes
.FindValue(name
);
1246 return wxPGVariantToInt(variant
, defVal
);
1249 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1252 wxVariant variant
= m_attributes
.FindValue(name
);
1254 if ( wxPGVariantToDouble(variant
, &retVal
) )
1260 wxVariant
wxPGProperty::GetAttributesAsList() const
1262 wxVariantList tempList
;
1263 wxVariant
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) );
1265 wxPGAttributeStorage::const_iterator it
= m_attributes
.StartIteration();
1268 while ( m_attributes
.GetNext(it
, variant
) )
1274 // Slots of utility flags are NULL
1275 const unsigned int gs_propFlagToStringSize
= 14;
1277 static const wxChar
* gs_propFlagToString
[gs_propFlagToStringSize
] = {
1294 wxString
wxPGProperty::GetFlagsAsString( FlagType flagsMask
) const
1297 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1301 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1303 if ( relevantFlags
& a
)
1305 const wxChar
* fs
= gs_propFlagToString
[i
];
1317 void wxPGProperty::SetFlagsFromString( const wxString
& str
)
1321 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1323 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1325 const wxChar
* fs
= gs_propFlagToString
[i
];
1326 if ( fs
&& str
== fs
)
1332 WX_PG_TOKENIZER1_END()
1334 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1337 wxValidator
* wxPGProperty::DoGetValidator() const
1339 return (wxValidator
*) NULL
;
1342 wxPGChoices
& wxPGProperty::GetChoices()
1344 wxPGChoiceInfo choiceInfo
;
1345 choiceInfo
.m_choices
= NULL
;
1346 GetChoiceInfo(&choiceInfo
);
1347 return *choiceInfo
.m_choices
;
1350 const wxPGChoices
& wxPGProperty::GetChoices() const
1352 return (const wxPGChoices
&) ((wxPGProperty
*)this)->GetChoices();
1355 unsigned int wxPGProperty::GetChoiceCount() const
1357 const wxPGChoices
& choices
= GetChoices();
1358 if ( &choices
&& choices
.IsOk() )
1359 return choices
.GetCount();
1363 const wxPGChoiceEntry
* wxPGProperty::GetCurrentChoice() const
1366 ci
.m_choices
= (wxPGChoices
*) NULL
;
1367 int index
= ((wxPGProperty
*)this)->GetChoiceInfo(&ci
);
1368 if ( index
== -1 || !ci
.m_choices
|| index
>= (int)ci
.m_choices
->GetCount() )
1371 return &(*ci
.m_choices
)[index
];
1374 bool wxPGProperty::SetChoices( wxPGChoices
& choices
)
1377 ci
.m_choices
= (wxPGChoices
*) NULL
;
1383 ci
.m_choices
->Assign(choices
);
1387 // This may be needed to trigger some initialization
1388 // (but don't do it if property is somewhat uninitialized)
1389 wxVariant defVal
= GetDefaultValue();
1390 if ( defVal
.IsNull() )
1402 const wxPGEditor
* wxPGProperty::GetEditorClass() const
1404 const wxPGEditor
* editor
;
1406 if ( !m_customEditor
)
1408 editor
= DoGetEditorClass();
1411 editor
= m_customEditor
;
1414 // Maybe override editor if common value specified
1415 if ( GetDisplayedCommonValueCount() )
1417 // TextCtrlAndButton -> ComboBoxAndButton
1418 if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) )
1419 editor
= wxPG_EDITOR(ChoiceAndButton
);
1421 // TextCtrl -> ComboBox
1422 else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) )
1423 editor
= wxPG_EDITOR(ComboBox
);
1430 // Privatizes set of choices
1431 void wxPGProperty::SetChoicesExclusive()
1434 ci
.m_choices
= (wxPGChoices
*) NULL
;
1438 ci
.m_choices
->SetExclusive();
1441 bool wxPGProperty::HasVisibleChildren() const
1445 for ( i
=0; i
<GetChildCount(); i
++ )
1447 wxPGProperty
* child
= Item(i
);
1449 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
1456 bool wxPGProperty::PrepareValueForDialogEditing( wxPropertyGrid
* propGrid
)
1458 return propGrid
->EditorValidate();
1462 bool wxPGProperty::RecreateEditor()
1464 wxPropertyGrid
* pg
= GetGrid();
1467 wxPGProperty
* selected
= pg
->GetSelection();
1468 if ( this == selected
)
1470 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
1477 void wxPGProperty::SetValueImage( wxBitmap
& bmp
)
1479 delete m_valueBitmap
;
1481 if ( &bmp
&& bmp
.Ok() )
1484 wxSize maxSz
= GetGrid()->GetImageSize();
1485 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
1487 if ( imSz
.x
!= maxSz
.x
|| imSz
.y
!= maxSz
.y
)
1489 // Create a memory DC
1490 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
1493 dc
.SelectObject(*bmpNew
);
1496 // FIXME: This is ugly - use image or wait for scaling patch.
1497 double scaleX
= (double)maxSz
.x
/ (double)imSz
.x
;
1498 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
1500 dc
.SetUserScale(scaleX
,scaleY
);
1502 dc
.DrawBitmap( bmp
, 0, 0 );
1504 m_valueBitmap
= bmpNew
;
1508 m_valueBitmap
= new wxBitmap(bmp
);
1511 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1515 m_valueBitmap
= NULL
;
1516 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
1521 wxPGProperty
* wxPGProperty::GetMainParent() const
1523 const wxPGProperty
* curChild
= this;
1524 const wxPGProperty
* curParent
= m_parent
;
1526 while ( curParent
&& !curParent
->IsCategory() )
1528 curChild
= curParent
;
1529 curParent
= curParent
->m_parent
;
1532 return (wxPGProperty
*) curChild
;
1536 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const
1539 // Returns last visible sub-item, recursively.
1540 if ( !IsExpanded() || !GetChildCount() )
1543 return Last()->GetLastVisibleSubItem();
1547 bool wxPGProperty::IsVisible() const
1549 const wxPGProperty
* parent
;
1551 if ( HasFlag(wxPG_PROP_HIDDEN
) )
1554 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
1556 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
1563 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const
1565 wxPropertyGridPageState
* state
= GetParentState();
1566 wxPropertyGrid
* propGrid
= state
->GetGrid();
1567 if ( state
== propGrid
->GetState() )
1573 int wxPGProperty::GetY2( int lh
) const
1575 const wxPGProperty
* parent
;
1576 const wxPGProperty
* child
= this;
1580 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
1582 if ( !parent
->IsExpanded() )
1584 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
1589 y
-= lh
; // need to reduce one level
1595 int wxPGProperty::GetY() const
1597 return GetY2(GetGrid()->GetRowHeight());
1601 wxPGProperty
* wxPGPropArgCls::GetPtr( wxPropertyGridInterface
* methods
) const
1605 wxASSERT_MSG( m_ptr
.property
, wxT("invalid property ptr") );
1606 return m_ptr
.property
;
1608 else if ( m_isName
== 1 )
1609 return methods
->GetPropertyByNameA(*m_ptr
.name
);
1610 else if ( m_isName
== 2 )
1611 return methods
->GetPropertyByNameA(m_ptr
.rawname
);
1612 // 3 is like 1, but ptr is freed in dtor - only needed by wxPython bindings.
1613 else if ( m_isName
== 3 )
1614 return methods
->GetPropertyByNameA(*m_ptr
.name
);
1616 wxASSERT( m_isName
<= 3 );
1620 // This is used by Insert etc.
1621 void wxPGProperty::AddChild2( wxPGProperty
* prop
, int index
, bool correct_mode
)
1623 if ( index
< 0 || (size_t)index
>= m_children
.GetCount() )
1625 if ( correct_mode
) prop
->m_arrIndex
= m_children
.GetCount();
1626 m_children
.Add( prop
);
1630 m_children
.Insert( prop
, index
);
1631 if ( correct_mode
) FixIndexesOfChildren( index
);
1634 prop
->m_parent
= this;
1637 // This is used by properties that have fixed sub-properties
1638 void wxPGProperty::AddChild( wxPGProperty
* prop
)
1640 prop
->m_arrIndex
= m_children
.GetCount();
1641 m_children
.Add( prop
);
1643 int custImgHeight
= prop
->OnMeasureImage().y
;
1644 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
1645 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1647 prop
->m_parent
= this;
1651 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
1653 wxASSERT( GetChildCount() );
1654 wxASSERT( !IsCategory() );
1656 *value
= GetValue();
1658 if ( !list
.GetCount() )
1661 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
1663 bool allChildrenSpecified
;
1665 // Don't fully update aggregate properties unless all children have
1667 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1668 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
1670 allChildrenSpecified
= true;
1672 wxVariant childValue
= list
[0];
1676 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetLabel().c_str());
1678 for ( i
=0; i
<GetChildCount(); i
++ )
1680 const wxPGProperty
* child
= Item(i
);
1682 if ( childValue
.GetName() == child
->GetLabel() )
1684 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
1686 if ( wxPGIsVariantType(childValue
, list
) )
1688 wxVariant
cv2(child
->GetValue());
1689 child
->AdaptListToValue(childValue
, &cv2
);
1693 if ( allChildrenSpecified
)
1694 ChildChanged(*value
, i
, childValue
);
1696 if ( n
== (unsigned int)list
.GetCount() )
1698 childValue
= list
[n
];
1704 void wxPGProperty::FixIndexesOfChildren( size_t starthere
)
1707 for ( i
=starthere
;i
<GetChildCount();i
++)
1708 Item(i
)->m_arrIndex
= i
;
1712 // Returns (direct) child property with given name (or NULL if not found)
1713 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name
) const
1717 for ( i
=0; i
<GetChildCount(); i
++ )
1719 wxPGProperty
* p
= Item(i
);
1720 if ( p
->m_name
== name
)
1724 // Does it have point, then?
1725 int pos
= name
.Find(wxS('.'));
1727 return (wxPGProperty
*) NULL
;
1729 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
1731 if ( !p
|| !p
->GetChildCount() )
1734 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
1737 wxPGProperty
* wxPGProperty::GetPropertyByLabelWH( const wxString
& label
, unsigned int hintIndex
) const
1739 unsigned int i
= hintIndex
;
1741 if ( i
>= GetChildCount() )
1744 unsigned int lastIndex
= i
- 1;
1746 if ( lastIndex
>= GetChildCount() )
1747 lastIndex
= GetChildCount() - 1;
1751 wxPGProperty
* p
= Item(i
);
1752 if ( p
->m_label
== label
)
1755 if ( i
== lastIndex
)
1759 if ( i
== GetChildCount() )
1766 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_
) const
1768 // Returns height of children, recursively, and
1769 // by taking expanded/collapsed status into account.
1771 // iMax is used when finding property y-positions.
1777 iMax_
= GetChildCount();
1779 unsigned int iMax
= iMax_
;
1781 wxASSERT( iMax
<= GetChildCount() );
1783 if ( !IsExpanded() && GetParent() )
1788 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
1790 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1792 if ( !pwc
->IsExpanded() ||
1793 pwc
->GetChildCount() == 0 )
1796 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
1805 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
, unsigned int lh
, unsigned int* nextItemY
) const
1807 wxASSERT( nextItemY
);
1809 // Linear search at the moment
1811 // nextItemY = y of next visible property, final value will be written back.
1812 wxPGProperty
* result
= NULL
;
1813 wxPGProperty
* current
= NULL
;
1814 unsigned int iy
= *nextItemY
;
1816 unsigned int iMax
= GetChildCount();
1820 wxPGProperty
* pwc
= Item(i
);
1822 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1833 if ( pwc
->IsExpanded() &&
1834 pwc
->GetChildCount() > 0 )
1836 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
1848 if ( !result
&& y
< iy
)
1855 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
1857 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
1860 return (wxPGProperty
*) result
;
1863 void wxPGProperty::Empty()
1866 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
1868 for ( i
=0; i
<GetChildCount(); i
++ )
1870 wxPGProperty
* p
= (wxPGProperty
*) Item(i
);
1878 void wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
1879 int WXUNUSED(childIndex
),
1880 wxVariant
& WXUNUSED(childValue
) ) const
1884 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList
) const
1888 const wxVariantList
* pList
= NULL
;
1889 wxVariantList::const_iterator node
;
1893 pList
= &pendingList
->GetList();
1894 node
= pList
->begin();
1897 // Children in list can be in any order, but we will give hint to
1898 // GetPropertyByLabelWH(). This optimizes for full list parsing.
1899 for ( i
=0; i
<GetChildCount(); i
++ )
1901 wxPGProperty
* child
= Item(i
);
1902 const wxVariant
* listValue
= NULL
;
1907 const wxString
& childLabel
= child
->GetLabel();
1909 for ( ; node
!= pList
->end(); node
++ )
1911 const wxVariant
& item
= *((const wxVariant
*)*node
);
1912 if ( item
.GetName() == childLabel
)
1922 value
= child
->GetValue();
1924 if ( value
.IsNull() )
1927 // Check recursively
1928 if ( child
->GetChildCount() )
1930 const wxVariant
* childList
= NULL
;
1932 if ( listValue
&& wxPGIsVariantType(*listValue
, list
) )
1933 childList
= listValue
;
1935 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
1943 wxPGProperty
* wxPGProperty::UpdateParentValues()
1945 wxPGProperty
* parent
= m_parent
;
1946 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
1947 !parent
->IsCategory() && !parent
->IsRoot() )
1950 parent
->GenerateComposedValue(s
, 0);
1951 parent
->m_value
= s
;
1952 return parent
->UpdateParentValues();
1957 bool wxPGProperty::IsTextEditable() const
1959 if ( HasFlag(wxPG_PROP_READONLY
) )
1962 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
1964 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
1971 // Call for after sub-properties added with AddChild
1972 void wxPGProperty::PrepareSubProperties()
1974 wxPropertyGridPageState
* state
= GetParentState();
1978 if ( !GetChildCount() )
1981 wxByte depth
= m_depth
+ 1;
1982 wxByte depthBgCol
= m_depthBgCol
;
1984 FlagType inheritFlags
= m_flags
& wxPG_INHERITED_PROPFLAGS
;
1986 wxByte bgColIndex
= m_bgColIndex
;
1987 wxByte fgColIndex
= m_fgColIndex
;
1990 // Set some values to the children
1993 wxPGProperty
* nparent
= this;
1995 while ( i
< nparent
->GetChildCount() )
1997 wxPGProperty
* np
= nparent
->Item(i
);
1999 np
->m_parentState
= state
;
2000 np
->m_flags
|= inheritFlags
; // Hideable also if parent.
2001 np
->m_depth
= depth
;
2002 np
->m_depthBgCol
= depthBgCol
;
2003 np
->m_bgColIndex
= bgColIndex
;
2004 np
->m_fgColIndex
= fgColIndex
;
2006 // Also handle children of children
2007 if ( np
->GetChildCount() > 0 )
2013 nparent
->SetParentalType(wxPG_PROP_AGGREGATE
);
2014 nparent
->SetExpanded(false);
2023 // After reaching last sibling, go back to processing
2024 // siblings of the parent
2025 while ( i
>= nparent
->GetChildCount() )
2027 // Exit the loop when top parent hit
2028 if ( nparent
== this )
2033 i
= nparent
->GetArrIndex() + 1;
2034 nparent
= nparent
->GetParent();
2039 // Call after fixed sub-properties added/removed after creation.
2040 // if oldSelInd >= 0 and < new max items, then selection is
2041 // moved to it. Note: oldSelInd -2 indicates that this property
2042 // should be selected.
2043 void wxPGProperty::SubPropsChanged( int oldSelInd
)
2045 wxPropertyGridPageState
* state
= GetParentState();
2046 wxPropertyGrid
* grid
= state
->GetGrid();
2048 PrepareSubProperties();
2050 wxPGProperty
* sel
= (wxPGProperty
*) NULL
;
2051 if ( oldSelInd
>= (int)m_children
.GetCount() )
2052 oldSelInd
= (int)m_children
.GetCount() - 1;
2054 if ( oldSelInd
>= 0 )
2055 sel
= (wxPGProperty
*) m_children
[oldSelInd
];
2056 else if ( oldSelInd
== -2 )
2060 state
->DoSelectProperty(sel
);
2062 if ( state
== grid
->GetState() )
2064 grid
->GetPanel()->Refresh();
2068 // -----------------------------------------------------------------------
2070 // -----------------------------------------------------------------------
2072 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2073 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2076 wxPGRootProperty::wxPGRootProperty()
2080 m_name
= wxS("<root>");
2087 wxPGRootProperty::~wxPGRootProperty()
2092 // -----------------------------------------------------------------------
2093 // wxPropertyCategory
2094 // -----------------------------------------------------------------------
2096 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2097 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2099 void wxPropertyCategory::Init()
2101 // don't set colour - prepareadditem method should do this
2102 SetParentalType(wxPG_PROP_CATEGORY
);
2103 m_capFgColIndex
= 1;
2107 wxPropertyCategory::wxPropertyCategory()
2114 wxPropertyCategory::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2115 : wxPGProperty(label
,name
)
2121 wxPropertyCategory::~wxPropertyCategory()
2126 wxString
wxPropertyCategory::GetValueAsString( int ) const
2128 return wxEmptyString
;
2131 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2133 if ( m_textExtent
> 0 )
2134 return m_textExtent
;
2136 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2140 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2143 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2147 // -----------------------------------------------------------------------
2148 // wxPGAttributeStorage
2149 // -----------------------------------------------------------------------
2151 wxPGAttributeStorage::wxPGAttributeStorage()
2155 wxPGAttributeStorage::~wxPGAttributeStorage()
2157 wxPGHashMapS2P::iterator it
;
2159 for ( it
= m_map
.begin(); it
!= m_map
.end(); it
++ )
2161 wxVariantData
* data
= (wxVariantData
*) it
->second
;
2166 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value
)
2168 wxVariantData
* data
= value
.GetData();
2171 wxPGHashMapS2P::iterator it
= m_map
.find(name
);
2172 if ( it
!= m_map
.end() )
2173 ((wxVariantData
*)it
->second
)->DecRef();