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"
23 #include "wx/object.h"
25 #include "wx/string.h"
28 #include "wx/window.h"
31 #include "wx/dcmemory.h"
32 #include "wx/button.h"
35 #include "wx/cursor.h"
36 #include "wx/dialog.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/choice.h"
40 #include "wx/stattext.h"
41 #include "wx/scrolwin.h"
42 #include "wx/dirdlg.h"
43 #include "wx/layout.h"
45 #include "wx/textdlg.h"
46 #include "wx/filedlg.h"
47 #include "wx/statusbr.h"
52 #include <wx/propgrid/propgrid.h>
57 #define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's
60 #define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing
63 // -----------------------------------------------------------------------
65 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect
)
67 #if defined(__WXMSW__) && !defined(__WXWINCE__)
68 // FIXME: Use DrawFocusRect code above (currently it draws solid line
69 // for caption focus but works ok for other stuff).
70 // Also, it seems that this code may not work in future wx versions.
71 dc
.SetLogicalFunction(wxINVERT
);
73 wxPen
pen(*wxBLACK
,1,wxDOT
);
74 pen
.SetCap(wxCAP_BUTT
);
76 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
78 dc
.DrawRectangle(rect
);
80 dc
.SetLogicalFunction(wxCOPY
);
82 dc
.SetLogicalFunction(wxINVERT
);
84 dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
));
85 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
87 dc
.DrawRectangle(rect
);
89 dc
.SetLogicalFunction(wxCOPY
);
93 // -----------------------------------------------------------------------
95 // -----------------------------------------------------------------------
97 wxSize
wxPGCellRenderer::GetImageSize( const wxPGProperty
* WXUNUSED(property
),
99 int WXUNUSED(item
) ) const
104 void wxPGCellRenderer::DrawText( wxDC
& dc
, const wxRect
& rect
,
105 int xOffset
, const wxString
& text
) const
108 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
110 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
111 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
114 void wxPGCellRenderer::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
115 int xOffset
, const wxString
& text
,
116 wxPGProperty
* property
,
117 const wxPGEditor
* editor
) const
120 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
122 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
129 rect2
.height
-= yOffset
;
130 editor
->DrawValue( dc
, rect2
, property
, text
);
135 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
140 void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
142 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
143 wxPGDrawFocusRect(dc
,focusRect
);
146 int wxPGCellRenderer::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
150 if ( !(flags
& Selected
) )
152 // Draw using wxPGCell information, if available
153 wxColour fgCol
= cell
.GetFgCol();
155 dc
.SetTextForeground(fgCol
);
157 wxColour bgCol
= cell
.GetBgCol();
162 dc
.DrawRectangle(rect
);
166 const wxBitmap
& bmp
= cell
.GetBitmap();
168 // In control, do not draw oversized bitmap
169 (!(flags
& Control
) || bmp
.GetHeight() < rect
.height
)
173 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
174 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
176 imageOffset
= bmp
.GetWidth();
182 // -----------------------------------------------------------------------
183 // wxPGDefaultRenderer
184 // -----------------------------------------------------------------------
186 void wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
,
187 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
188 int column
, int item
, int flags
) const
190 bool isUnspecified
= property
->IsValueUnspecified();
192 if ( column
== 1 && item
== -1 )
194 int cmnVal
= property
->GetCommonValue();
198 if ( !isUnspecified
)
199 DrawText( dc
, rect
, 0, propertyGrid
->GetCommonValueLabel(cmnVal
) );
204 const wxPGEditor
* editor
= NULL
;
205 const wxPGCell
* cell
= property
->GetCell(column
);
211 if ( column
== 1 && (flags
& Control
) )
213 int selectedIndex
= property
->GetChoiceSelection();
214 if ( selectedIndex
!= wxNOT_FOUND
)
216 const wxPGChoices
& choices
= property
->GetChoices();
217 const wxPGCell
* ccell
= &choices
[selectedIndex
];
219 ( ccell
->GetBitmap().IsOk() || ccell
->GetFgCol().IsOk() || ccell
->GetBgCol().IsOk() )
227 int preDrawFlags
= flags
;
229 if ( propertyGrid
->GetInternalFlags() & wxPG_FL_CELL_OVERRIDES_SEL
)
230 preDrawFlags
= preDrawFlags
& ~(Selected
);
232 imageOffset
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
233 text
= cell
->GetText();
234 if ( text
== wxS("@!") )
237 text
= property
->GetLabel();
238 else if ( column
== 1 )
239 text
= property
->GetValueString();
241 text
= wxEmptyString
;
244 else if ( column
== 0 )
247 DrawText( dc
, rect
, 0, property
->GetLabel() );
249 else if ( column
== 1 )
251 if ( !isUnspecified
)
253 editor
= property
->GetColumnEditor(column
);
255 // Regular property value
257 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
259 wxPGPaintData paintdata
;
260 paintdata
.m_parent
= propertyGrid
;
261 paintdata
.m_choiceItem
= item
;
263 if ( imageSize
.x
> 0 )
265 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
266 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
267 wxPG_CUSTOM_IMAGE_WIDTH
,
268 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
270 /*if ( imageSize.x == wxPG_FULL_CUSTOM_PAINT_WIDTH )
272 imageRect.width = m_width - imageRect.x;
275 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
277 paintdata
.m_drawnWidth
= imageSize
.x
;
278 paintdata
.m_drawnHeight
= imageSize
.y
;
280 if ( !isUnspecified
)
282 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
286 dc
.SetBrush(*wxWHITE_BRUSH
);
287 dc
.DrawRectangle(imageRect
);
290 imageOffset
= paintdata
.m_drawnWidth
;
293 text
= property
->GetValueString();
296 if ( propertyGrid
->GetColumnCount() <= 2 )
298 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
299 if ( unitsString
.length() )
300 text
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
304 if ( text
.length() == 0 )
306 // Try to show inline help if no text
307 wxVariant vInlineHelp
= property
->GetAttribute(wxPGGlobalVars
->m_strInlineHelp
);
308 if ( !vInlineHelp
.IsNull() )
310 text
= vInlineHelp
.GetString();
311 dc
.SetTextForeground(propertyGrid
->GetCellDisabledTextColour());
315 else if ( column
== 2 )
318 if ( !text
.length() )
319 text
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
322 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
324 // active caption gets nice dotted rectangle
325 if ( property
->IsCategory() /*&& column == 0*/ )
327 if ( flags
& Selected
)
329 if ( imageOffset
> 0 )
330 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
332 DrawCaptionSelectionRect( dc
,
333 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
334 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
335 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
336 propertyGrid
->GetCaptionFont())
337 +(wxPG_CAPRECTXMARGIN
*2),
338 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
343 wxSize
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
,
347 if ( property
&& column
== 1 )
351 wxBitmap
* bmp
= property
->GetValueImage();
353 if ( bmp
&& bmp
->Ok() )
354 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
360 // -----------------------------------------------------------------------
362 // -----------------------------------------------------------------------
368 wxPGCell::wxPGCell( const wxString
& text
,
369 const wxBitmap
& bitmap
,
370 const wxColour
& fgCol
,
371 const wxColour
& bgCol
)
372 : m_bitmap(bitmap
), m_fgCol(fgCol
), m_bgCol(bgCol
)
377 // -----------------------------------------------------------------------
379 // -----------------------------------------------------------------------
381 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
383 wxString
* wxPGProperty::sm_wxPG_LABEL
= NULL
;
385 void wxPGProperty::Init()
391 m_parentState
= (wxPropertyGridPageState
*) NULL
;
394 m_clientObject
= NULL
;
396 m_customEditor
= (wxPGEditor
*) NULL
;
398 m_validator
= (wxValidator
*) NULL
;
400 m_valueBitmap
= (wxBitmap
*) NULL
;
402 m_maxLen
= 0; // infinite maximum length
404 m_flags
= wxPG_PROP_PROPERTY
;
414 void wxPGProperty::Init( const wxString
& label
, const wxString
& name
)
416 // We really need to check if &label and &name are NULL pointers
417 // (this can if we are called before property grid has been initalized)
419 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
422 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
425 DoSetName( m_label
);
430 wxPGProperty::wxPGProperty()
437 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name
)
444 wxPGProperty::~wxPGProperty()
446 delete m_clientObject
;
448 Empty(); // this deletes items
450 delete m_valueBitmap
;
457 for ( i
=0; i
<m_cells
.size(); i
++ )
458 delete (wxPGCell
*) m_cells
[i
];
460 // This makes it easier for us to detect dangling pointers
465 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate
) const
467 wxPGProperty
* parent
= m_parent
;
470 if ( parent
== candidate
)
472 parent
= parent
->m_parent
;
478 wxString
wxPGProperty::GetName() const
480 wxPGProperty
* parent
= GetParent();
482 if ( !m_name
.length() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
485 return m_parent
->GetName() + wxS(".") + m_name
;
488 wxPropertyGrid
* wxPGProperty::GetGrid() const
490 if ( !m_parentState
)
492 return m_parentState
->GetGrid();
496 void wxPGProperty::UpdateControl( wxWindow
* primary
)
499 GetEditorClass()->UpdateControl(this, primary
);
502 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
507 void wxPGProperty::OnSetValue()
511 void wxPGProperty::RefreshChildren ()
515 wxString
wxPGProperty::GetColumnText( unsigned int col
) const
517 wxPGCell
* cell
= GetCell(col
);
520 return cell
->GetText();
527 return GetDisplayedString();
529 return GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
532 return wxEmptyString
;
535 void wxPGProperty::GenerateComposedValue( wxString
& text
, int argFlags
) const
538 int iMax
= m_children
.GetCount();
544 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
545 !(argFlags
& wxPG_FULL_VALUE
) )
546 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
548 int iMaxMinusOne
= iMax
-1;
550 if ( !IsTextEditable() )
551 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
553 wxPGProperty
* curChild
= (wxPGProperty
*) m_children
.Item(0);
555 for ( i
= 0; i
< iMax
; i
++ )
558 if ( !curChild
->IsValueUnspecified() )
559 s
= curChild
->GetValueString(argFlags
|wxPG_COMPOSITE_FRAGMENT
);
562 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() )
565 if ( !curChild
->GetChildCount() || skip
)
568 text
+= wxS("[") + s
+ wxS("]");
570 if ( i
< iMaxMinusOne
)
572 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
573 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
574 !(argFlags
& wxPG_FULL_VALUE
) )
579 if ( !curChild
->GetChildCount() )
585 curChild
= (wxPGProperty
*) m_children
.Item(i
+1);
589 // Remove superfluous semicolon and space
591 if ( text
.EndsWith(wxS("; "), &rest
) )
594 if ( (unsigned int)i
< m_children
.GetCount() )
595 text
+= wxS("; ...");
598 wxString
wxPGProperty::GetValueAsString( int argFlags
) const
600 wxCHECK_MSG( GetChildCount() > 0,
602 wxT("If user property does not have any children, it must override GetValueAsString") );
605 GenerateComposedValue(text
, argFlags
);
609 wxString
wxPGProperty::GetValueString( int argFlags
) const
611 if ( IsValueUnspecified() )
612 return wxEmptyString
;
614 if ( m_commonValue
== -1 )
615 return GetValueAsString(argFlags
);
618 // Return common value's string representation
619 wxPropertyGrid
* pg
= GetGrid();
620 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
622 if ( argFlags
& wxPG_FULL_VALUE
)
624 return cv
->GetLabel();
626 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
628 return cv
->GetEditableText();
632 return cv
->GetLabel();
636 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
638 variant
= (long)number
;
642 // Convert semicolon delimited tokens into child values.
643 bool wxPGProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
645 if ( !GetChildCount() )
648 unsigned int curChild
= 0;
650 unsigned int iMax
= m_children
.GetCount();
652 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
653 !(argFlags
& wxPG_FULL_VALUE
) )
654 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
656 bool changed
= false;
661 // Its best only to add non-empty group items
662 bool addOnlyIfNotEmpty
= false;
663 const wxChar delimeter
= wxS(';');
665 size_t tokenStart
= 0xFFFFFF;
667 wxVariantList temp_list
;
668 wxVariant
list(temp_list
);
670 int propagatedFlags
= argFlags
& wxPG_REPORT_ERROR
;
673 bool debug_print
= false;
678 wxLogDebug(wxT(">> %s.StringToValue('%s')"),GetLabel().c_str(),text
.c_str());
681 wxString::const_iterator it
= text
.begin();
684 if ( it
!= text
.end() )
691 if ( tokenStart
!= 0xFFFFFF )
694 if ( a
== delimeter
|| a
== 0 )
696 token
= text
.substr(tokenStart
,pos
-tokenStart
);
698 size_t len
= token
.length();
700 if ( !addOnlyIfNotEmpty
|| len
> 0 )
702 const wxPGProperty
* child
= Item(curChild
);
705 wxLogDebug(wxT("token = '%s', child = %s"),token
.c_str(),child
->GetLabel().c_str());
710 bool wasUnspecified
= child
->IsValueUnspecified();
712 wxVariant
variant(child
->GetValueRef());
713 if ( child
->StringToValue(variant
, token
, propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
715 variant
.SetName(child
->GetBaseName());
717 // Clear unspecified flag only if OnSetValue() didn't
719 if ( child
->IsValueUnspecified() &&
720 (wasUnspecified
|| !UsesAutoUnspecified()) )
722 variant
= child
->GetDefaultValue();
725 list
.Append(variant
);
732 // Empty, becomes unspecified
734 variant2
.SetName(child
->GetBaseName());
735 list
.Append(variant2
);
740 if ( curChild
>= iMax
)
744 tokenStart
= 0xFFFFFF;
749 // Token is not running
753 addOnlyIfNotEmpty
= false;
755 // Is this a group of tokens?
760 if ( it
!= text
.end() ) it
++;
762 size_t startPos
= pos
;
764 // Group item - find end
765 while ( it
!= text
.end() && depth
> 0 )
773 else if ( a
== wxS('[') )
777 token
= text
.substr(startPos
,pos
-startPos
-1);
779 if ( !token
.length() )
782 const wxPGProperty
* child
= Item(curChild
);
784 wxVariant oldChildValue
= child
->GetValue();
785 wxVariant
variant(oldChildValue
);
786 bool stvRes
= child
->StringToValue( variant
, token
, propagatedFlags
);
787 if ( stvRes
|| (variant
!= oldChildValue
) )
794 // Failed, becomes unspecified
799 variant
.SetName(child
->GetBaseName());
800 list
.Append(variant
);
803 if ( curChild
>= iMax
)
806 addOnlyIfNotEmpty
= true;
808 tokenStart
= 0xFFFFFF;
814 if ( a
== delimeter
)
827 if ( it
!= text
.end() )
844 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags
)
846 wxVariant
variant(m_value
);
847 bool res
= StringToValue(variant
, text
, argFlags
);
853 bool wxPGProperty::SetValueFromInt( long number
, int argFlags
)
855 wxVariant
variant(m_value
);
856 bool res
= IntToValue(variant
, number
, argFlags
);
862 wxSize
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const
865 return wxSize(m_valueBitmap
->GetWidth(),-1);
870 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const
872 return wxPGGlobalVars
->m_defaultRenderer
;
875 void wxPGProperty::OnCustomPaint( wxDC
& dc
,
879 wxBitmap
* bmp
= m_valueBitmap
;
881 wxCHECK_RET( bmp
&& bmp
->Ok(), wxT("invalid bitmap") );
883 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
885 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
888 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const
890 return wxPG_EDITOR(TextCtrl
);
893 // Default extra property event handling - that is, none at all.
894 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
900 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
902 if ( !value
.IsNull() )
904 wxVariant tempListVariant
;
907 // List variants are reserved a special purpose
908 // as intermediate containers for child values
909 // of properties with children.
910 if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST
)
913 // However, situation is different for composed string properties
914 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
916 tempListVariant
= value
;
917 pList
= &tempListVariant
;
921 AdaptListToValue(value
, &newValue
);
923 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
926 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
927 flags
|= wxPG_SETVAL_AGGREGATED
;
929 if ( pList
&& !pList
->IsNull() )
931 wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST
);
932 wxASSERT( GetChildCount() );
933 wxASSERT( !IsCategory() );
935 wxVariantList
& list
= pList
->GetList();
936 wxVariantList::iterator node
;
939 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
941 // Children in list can be in any order, but we will give hint to
942 // GetPropertyByNameWH(). This optimizes for full list parsing.
943 for ( node
= list
.begin(); node
!= list
.end(); node
++ )
945 wxVariant
& childValue
= *((wxVariant
*)*node
);
946 wxPGProperty
* child
= GetPropertyByNameWH(childValue
.GetName(), i
);
949 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
950 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
952 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
954 wxVariant listRefCopy
= childValue
;
955 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
959 wxVariant oldVal
= child
->GetValue();
960 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
963 else if ( child
->GetValue() != childValue
)
965 // For aggregate properties, we will trust RefreshChildren()
966 // to update child values.
967 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
968 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
969 if ( flags
& wxPG_SETVAL_BY_USER
)
970 child
->SetFlag(wxPG_PROP_MODIFIED
);
977 if ( !value
.IsNull() )
982 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
983 UpdateParentValues();
986 if ( flags
& wxPG_SETVAL_BY_USER
)
987 SetFlag(wxPG_PROP_MODIFIED
);
989 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
994 if ( m_commonValue
!= -1 )
996 wxPropertyGrid
* pg
= GetGrid();
997 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
1003 // Set children to unspecified, but only if aggregate or
1004 // value is <composed>
1005 if ( AreChildrenComponents() )
1008 for ( i
=0; i
<GetChildCount(); i
++ )
1009 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1014 // Update editor control
1017 // We need to check for these, otherwise GetGrid() may fail.
1018 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1023 void wxPGProperty::SetValueInEvent( wxVariant value
) const
1025 GetGrid()->ValueChangeInEvent(value
);
1028 void wxPGProperty::SetFlagRecursively( FlagType flag
, bool set
)
1036 for ( i
= 0; i
< GetChildCount(); i
++ )
1037 Item(i
)->SetFlagRecursively(flag
, set
);
1040 void wxPGProperty::RefreshEditor()
1042 if ( m_parent
&& GetParentState() )
1044 wxPropertyGrid
* pg
= GetParentState()->GetGrid();
1045 if ( pg
->GetSelectedProperty() == this )
1047 wxWindow
* editor
= pg
->GetEditorControl();
1049 GetEditorClass()->UpdateControl( this, editor
);
1055 wxVariant
wxPGProperty::GetDefaultValue() const
1057 wxVariant defVal
= GetAttribute(wxS("DefaultValue"));
1058 if ( !defVal
.IsNull() )
1061 wxVariant value
= GetValue();
1063 if ( !value
.IsNull() )
1065 wxString
valueType(value
.GetType());
1067 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1068 return wxPGVariant_Zero
;
1069 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1070 return wxPGVariant_EmptyString
;
1071 if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1072 return wxPGVariant_False
;
1073 if ( valueType
== wxPG_VARIANT_TYPE_DOUBLE
)
1074 return wxVariant(0.0);
1075 if ( valueType
== wxPG_VARIANT_TYPE_ARRSTRING
)
1076 return wxVariant(wxArrayString());
1077 if ( valueType
== wxS("wxLongLong") )
1078 return WXVARIANT(wxLongLong(0));
1079 if ( valueType
== wxS("wxULongLong") )
1080 return WXVARIANT(wxULongLong(0));
1081 if ( valueType
== wxS("wxColour") )
1082 return WXVARIANT(*wxBLACK
);
1084 if ( valueType
== wxPG_VARIANT_TYPE_DATETIME
)
1085 return wxVariant(wxDateTime::Now());
1087 if ( valueType
== wxS("wxFont") )
1088 return WXVARIANT(*wxNORMAL_FONT
);
1089 if ( valueType
== wxS("wxPoint") )
1090 return WXVARIANT(wxPoint(0, 0));
1091 if ( valueType
== wxS("wxSize") )
1092 return WXVARIANT(wxSize(0, 0));
1098 void wxPGProperty::SetCell( int column
, wxPGCell
* cellObj
)
1100 if ( column
>= (int)m_cells
.size() )
1101 m_cells
.SetCount(column
+1, NULL
);
1103 delete (wxPGCell
*) m_cells
[column
];
1104 m_cells
[column
] = cellObj
;
1107 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const
1112 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1117 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value
)
1119 if ( DoSetAttribute( name
, value
) )
1121 // Support working without grid, when possible
1122 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1126 m_attributes
.Set( name
, value
);
1129 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes
)
1131 wxPGAttributeStorage::const_iterator it
= attributes
.StartIteration();
1134 while ( attributes
.GetNext(it
, variant
) )
1135 SetAttribute( variant
.GetName(), variant
);
1138 wxVariant
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1144 wxVariant
wxPGProperty::GetAttribute( const wxString
& name
) const
1146 return m_attributes
.FindValue(name
);
1149 wxString
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1151 wxVariant variant
= m_attributes
.FindValue(name
);
1153 if ( !variant
.IsNull() )
1154 return variant
.GetString();
1159 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1161 wxVariant variant
= m_attributes
.FindValue(name
);
1163 return wxPGVariantToInt(variant
, defVal
);
1166 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1169 wxVariant variant
= m_attributes
.FindValue(name
);
1171 if ( wxPGVariantToDouble(variant
, &retVal
) )
1177 wxVariant
wxPGProperty::GetAttributesAsList() const
1179 wxVariantList tempList
;
1180 wxVariant
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) );
1182 wxPGAttributeStorage::const_iterator it
= m_attributes
.StartIteration();
1185 while ( m_attributes
.GetNext(it
, variant
) )
1191 // Slots of utility flags are NULL
1192 const unsigned int gs_propFlagToStringSize
= 14;
1194 static const wxChar
* gs_propFlagToString
[gs_propFlagToStringSize
] = {
1211 wxString
wxPGProperty::GetFlagsAsString( FlagType flagsMask
) const
1214 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1218 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1220 if ( relevantFlags
& a
)
1222 const wxChar
* fs
= gs_propFlagToString
[i
];
1234 void wxPGProperty::SetFlagsFromString( const wxString
& str
)
1238 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1240 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1242 const wxChar
* fs
= gs_propFlagToString
[i
];
1243 if ( fs
&& str
== fs
)
1249 WX_PG_TOKENIZER1_END()
1251 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1254 wxValidator
* wxPGProperty::DoGetValidator() const
1256 return (wxValidator
*) NULL
;
1259 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value
)
1261 wxPropertyGrid
* pg
= GetGrid();
1262 int sel
= GetChoiceSelection();
1266 if ( index
== wxNOT_FOUND
)
1267 index
= m_choices
.GetCount();
1272 m_choices
.Insert(label
, index
, value
);
1274 if ( sel
!= newSel
)
1275 SetChoiceSelection(newSel
);
1277 if ( this == pg
->GetSelection() )
1278 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1284 void wxPGProperty::DeleteChoice( int index
)
1286 wxPropertyGrid
* pg
= GetGrid();
1288 int sel
= GetChoiceSelection();
1291 // Adjust current value
1294 SetValueToUnspecified();
1297 else if ( index
< sel
)
1302 m_choices
.RemoveAt(index
);
1304 if ( sel
!= newSel
)
1305 SetChoiceSelection(newSel
);
1307 if ( this == pg
->GetSelection() )
1308 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1311 int wxPGProperty::GetChoiceSelection() const
1313 wxVariant value
= GetValue();
1314 wxString valueType
= value
.GetType();
1315 int index
= wxNOT_FOUND
;
1317 if ( IsValueUnspecified() || !m_choices
.GetCount() )
1320 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1322 index
= value
.GetLong();
1324 else if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1326 index
= m_choices
.Index(value
.GetString());
1328 else if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1330 index
= value
.GetBool()? 1 : 0;
1336 void wxPGProperty::SetChoiceSelection( int newValue
)
1338 // Changes value of a property with choices, but only
1339 // works if the value type is long or string.
1340 wxString valueType
= GetValue().GetType();
1342 wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") );
1344 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1346 SetValue( m_choices
.GetLabel(newValue
) );
1348 else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
1350 SetValue( (long) newValue
);
1354 bool wxPGProperty::SetChoices( wxPGChoices
& choices
)
1356 m_choices
.Assign(choices
);
1359 // This may be needed to trigger some initialization
1360 // (but don't do it if property is somewhat uninitialized)
1361 wxVariant defVal
= GetDefaultValue();
1362 if ( defVal
.IsNull() )
1372 const wxPGEditor
* wxPGProperty::GetEditorClass() const
1374 const wxPGEditor
* editor
;
1376 if ( !m_customEditor
)
1378 editor
= DoGetEditorClass();
1381 editor
= m_customEditor
;
1384 // Maybe override editor if common value specified
1385 if ( GetDisplayedCommonValueCount() )
1387 // TextCtrlAndButton -> ComboBoxAndButton
1388 if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) )
1389 editor
= wxPG_EDITOR(ChoiceAndButton
);
1391 // TextCtrl -> ComboBox
1392 else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) )
1393 editor
= wxPG_EDITOR(ComboBox
);
1399 bool wxPGProperty::HasVisibleChildren() const
1403 for ( i
=0; i
<GetChildCount(); i
++ )
1405 wxPGProperty
* child
= Item(i
);
1407 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
1414 bool wxPGProperty::PrepareValueForDialogEditing( wxPropertyGrid
* propGrid
)
1416 return propGrid
->EditorValidate();
1420 bool wxPGProperty::RecreateEditor()
1422 wxPropertyGrid
* pg
= GetGrid();
1425 wxPGProperty
* selected
= pg
->GetSelection();
1426 if ( this == selected
)
1428 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
1435 void wxPGProperty::SetValueImage( wxBitmap
& bmp
)
1437 delete m_valueBitmap
;
1439 if ( &bmp
&& bmp
.Ok() )
1442 wxSize maxSz
= GetGrid()->GetImageSize();
1443 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
1445 if ( imSz
.x
!= maxSz
.x
|| imSz
.y
!= maxSz
.y
)
1447 // Create a memory DC
1448 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
1451 dc
.SelectObject(*bmpNew
);
1454 // FIXME: This is ugly - use image or wait for scaling patch.
1455 double scaleX
= (double)maxSz
.x
/ (double)imSz
.x
;
1456 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
1458 dc
.SetUserScale(scaleX
,scaleY
);
1460 dc
.DrawBitmap( bmp
, 0, 0 );
1462 m_valueBitmap
= bmpNew
;
1466 m_valueBitmap
= new wxBitmap(bmp
);
1469 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1473 m_valueBitmap
= NULL
;
1474 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
1479 wxPGProperty
* wxPGProperty::GetMainParent() const
1481 const wxPGProperty
* curChild
= this;
1482 const wxPGProperty
* curParent
= m_parent
;
1484 while ( curParent
&& !curParent
->IsCategory() )
1486 curChild
= curParent
;
1487 curParent
= curParent
->m_parent
;
1490 return (wxPGProperty
*) curChild
;
1494 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const
1497 // Returns last visible sub-item, recursively.
1498 if ( !IsExpanded() || !GetChildCount() )
1501 return Last()->GetLastVisibleSubItem();
1505 bool wxPGProperty::IsVisible() const
1507 const wxPGProperty
* parent
;
1509 if ( HasFlag(wxPG_PROP_HIDDEN
) )
1512 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
1514 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
1521 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const
1523 wxPropertyGridPageState
* state
= GetParentState();
1524 wxPropertyGrid
* propGrid
= state
->GetGrid();
1525 if ( state
== propGrid
->GetState() )
1531 int wxPGProperty::GetY2( int lh
) const
1533 const wxPGProperty
* parent
;
1534 const wxPGProperty
* child
= this;
1538 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
1540 if ( !parent
->IsExpanded() )
1542 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
1547 y
-= lh
; // need to reduce one level
1553 int wxPGProperty::GetY() const
1555 return GetY2(GetGrid()->GetRowHeight());
1558 // This is used by Insert etc.
1559 void wxPGProperty::AddChild2( wxPGProperty
* prop
, int index
, bool correct_mode
)
1561 if ( index
< 0 || (size_t)index
>= m_children
.GetCount() )
1563 if ( correct_mode
) prop
->m_arrIndex
= m_children
.GetCount();
1564 m_children
.Add( prop
);
1568 m_children
.Insert( prop
, index
);
1569 if ( correct_mode
) FixIndexesOfChildren( index
);
1572 prop
->m_parent
= this;
1575 // This is used by properties that have fixed sub-properties
1576 void wxPGProperty::AddChild( wxPGProperty
* prop
)
1578 wxASSERT_MSG( prop
->GetBaseName().length(),
1579 "Property's children must have unique, non-empty names within their scope" );
1581 prop
->m_arrIndex
= m_children
.GetCount();
1582 m_children
.Add( prop
);
1584 int custImgHeight
= prop
->OnMeasureImage().y
;
1585 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
1586 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1588 prop
->m_parent
= this;
1592 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
1594 wxASSERT( GetChildCount() );
1595 wxASSERT( !IsCategory() );
1597 *value
= GetValue();
1599 if ( !list
.GetCount() )
1602 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
1604 bool allChildrenSpecified
;
1606 // Don't fully update aggregate properties unless all children have
1608 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1609 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
1611 allChildrenSpecified
= true;
1613 wxVariant childValue
= list
[0];
1617 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
1619 for ( i
=0; i
<GetChildCount(); i
++ )
1621 const wxPGProperty
* child
= Item(i
);
1623 if ( childValue
.GetName() == child
->GetBaseName() )
1625 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
1627 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1629 wxVariant
cv2(child
->GetValue());
1630 child
->AdaptListToValue(childValue
, &cv2
);
1634 if ( allChildrenSpecified
)
1635 ChildChanged(*value
, i
, childValue
);
1637 if ( n
== (unsigned int)list
.GetCount() )
1639 childValue
= list
[n
];
1645 void wxPGProperty::FixIndexesOfChildren( size_t starthere
)
1648 for ( i
=starthere
;i
<GetChildCount();i
++)
1649 Item(i
)->m_arrIndex
= i
;
1653 // Returns (direct) child property with given name (or NULL if not found)
1654 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name
) const
1658 for ( i
=0; i
<GetChildCount(); i
++ )
1660 wxPGProperty
* p
= Item(i
);
1661 if ( p
->m_name
== name
)
1665 // Does it have point, then?
1666 int pos
= name
.Find(wxS('.'));
1668 return (wxPGProperty
*) NULL
;
1670 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
1672 if ( !p
|| !p
->GetChildCount() )
1675 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
1678 wxPGProperty
* wxPGProperty::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex
) const
1680 unsigned int i
= hintIndex
;
1682 if ( i
>= GetChildCount() )
1685 unsigned int lastIndex
= i
- 1;
1687 if ( lastIndex
>= GetChildCount() )
1688 lastIndex
= GetChildCount() - 1;
1692 wxPGProperty
* p
= Item(i
);
1693 if ( p
->m_name
== name
)
1696 if ( i
== lastIndex
)
1700 if ( i
== GetChildCount() )
1707 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_
) const
1709 // Returns height of children, recursively, and
1710 // by taking expanded/collapsed status into account.
1712 // iMax is used when finding property y-positions.
1718 iMax_
= GetChildCount();
1720 unsigned int iMax
= iMax_
;
1722 wxASSERT( iMax
<= GetChildCount() );
1724 if ( !IsExpanded() && GetParent() )
1729 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
1731 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1733 if ( !pwc
->IsExpanded() ||
1734 pwc
->GetChildCount() == 0 )
1737 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
1746 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
, unsigned int lh
, unsigned int* nextItemY
) const
1748 wxASSERT( nextItemY
);
1750 // Linear search at the moment
1752 // nextItemY = y of next visible property, final value will be written back.
1753 wxPGProperty
* result
= NULL
;
1754 wxPGProperty
* current
= NULL
;
1755 unsigned int iy
= *nextItemY
;
1757 unsigned int iMax
= GetChildCount();
1761 wxPGProperty
* pwc
= Item(i
);
1763 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1774 if ( pwc
->IsExpanded() &&
1775 pwc
->GetChildCount() > 0 )
1777 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
1789 if ( !result
&& y
< iy
)
1796 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
1798 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
1801 return (wxPGProperty
*) result
;
1804 void wxPGProperty::Empty()
1807 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
1809 for ( i
=0; i
<GetChildCount(); i
++ )
1811 wxPGProperty
* p
= (wxPGProperty
*) Item(i
);
1819 void wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
1820 int WXUNUSED(childIndex
),
1821 wxVariant
& WXUNUSED(childValue
) ) const
1825 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList
) const
1829 const wxVariantList
* pList
= NULL
;
1830 wxVariantList::const_iterator node
;
1834 pList
= &pendingList
->GetList();
1835 node
= pList
->begin();
1838 for ( i
=0; i
<GetChildCount(); i
++ )
1840 wxPGProperty
* child
= Item(i
);
1841 const wxVariant
* listValue
= NULL
;
1846 const wxString
& childName
= child
->GetBaseName();
1848 for ( ; node
!= pList
->end(); node
++ )
1850 const wxVariant
& item
= *((const wxVariant
*)*node
);
1851 if ( item
.GetName() == childName
)
1861 value
= child
->GetValue();
1863 if ( value
.IsNull() )
1866 // Check recursively
1867 if ( child
->GetChildCount() )
1869 const wxVariant
* childList
= NULL
;
1871 if ( listValue
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST
)
1872 childList
= listValue
;
1874 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
1882 wxPGProperty
* wxPGProperty::UpdateParentValues()
1884 wxPGProperty
* parent
= m_parent
;
1885 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
1886 !parent
->IsCategory() && !parent
->IsRoot() )
1889 parent
->GenerateComposedValue(s
, 0);
1890 parent
->m_value
= s
;
1891 return parent
->UpdateParentValues();
1896 bool wxPGProperty::IsTextEditable() const
1898 if ( HasFlag(wxPG_PROP_READONLY
) )
1901 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
1903 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
1910 // Call for after sub-properties added with AddChild
1911 void wxPGProperty::PrepareSubProperties()
1913 wxPropertyGridPageState
* state
= GetParentState();
1917 if ( !GetChildCount() )
1920 wxByte depth
= m_depth
+ 1;
1921 wxByte depthBgCol
= m_depthBgCol
;
1923 FlagType inheritFlags
= m_flags
& wxPG_INHERITED_PROPFLAGS
;
1925 wxByte bgColIndex
= m_bgColIndex
;
1926 wxByte fgColIndex
= m_fgColIndex
;
1929 // Set some values to the children
1932 wxPGProperty
* nparent
= this;
1934 while ( i
< nparent
->GetChildCount() )
1936 wxPGProperty
* np
= nparent
->Item(i
);
1938 np
->m_parentState
= state
;
1939 np
->m_flags
|= inheritFlags
; // Hideable also if parent.
1940 np
->m_depth
= depth
;
1941 np
->m_depthBgCol
= depthBgCol
;
1942 np
->m_bgColIndex
= bgColIndex
;
1943 np
->m_fgColIndex
= fgColIndex
;
1945 // Also handle children of children
1946 if ( np
->GetChildCount() > 0 )
1952 nparent
->SetParentalType(wxPG_PROP_AGGREGATE
);
1953 nparent
->SetExpanded(false);
1962 // After reaching last sibling, go back to processing
1963 // siblings of the parent
1964 while ( i
>= nparent
->GetChildCount() )
1966 // Exit the loop when top parent hit
1967 if ( nparent
== this )
1972 i
= nparent
->GetArrIndex() + 1;
1973 nparent
= nparent
->GetParent();
1978 // Call after fixed sub-properties added/removed after creation.
1979 // if oldSelInd >= 0 and < new max items, then selection is
1980 // moved to it. Note: oldSelInd -2 indicates that this property
1981 // should be selected.
1982 void wxPGProperty::SubPropsChanged( int oldSelInd
)
1984 wxPropertyGridPageState
* state
= GetParentState();
1985 wxPropertyGrid
* grid
= state
->GetGrid();
1987 PrepareSubProperties();
1989 wxPGProperty
* sel
= (wxPGProperty
*) NULL
;
1990 if ( oldSelInd
>= (int)m_children
.GetCount() )
1991 oldSelInd
= (int)m_children
.GetCount() - 1;
1993 if ( oldSelInd
>= 0 )
1994 sel
= (wxPGProperty
*) m_children
[oldSelInd
];
1995 else if ( oldSelInd
== -2 )
1999 state
->DoSelectProperty(sel
);
2001 if ( state
== grid
->GetState() )
2003 grid
->GetPanel()->Refresh();
2007 // -----------------------------------------------------------------------
2009 // -----------------------------------------------------------------------
2011 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2012 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2015 wxPGRootProperty::wxPGRootProperty()
2019 m_name
= wxS("<root>");
2026 wxPGRootProperty::~wxPGRootProperty()
2031 // -----------------------------------------------------------------------
2032 // wxPropertyCategory
2033 // -----------------------------------------------------------------------
2035 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2036 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2038 void wxPropertyCategory::Init()
2040 // don't set colour - prepareadditem method should do this
2041 SetParentalType(wxPG_PROP_CATEGORY
);
2042 m_capFgColIndex
= 1;
2046 wxPropertyCategory::wxPropertyCategory()
2053 wxPropertyCategory::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2054 : wxPGProperty(label
,name
)
2060 wxPropertyCategory::~wxPropertyCategory()
2065 wxString
wxPropertyCategory::GetValueAsString( int ) const
2067 return wxEmptyString
;
2070 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2072 if ( m_textExtent
> 0 )
2073 return m_textExtent
;
2075 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2079 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2082 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2086 // -----------------------------------------------------------------------
2087 // wxPGAttributeStorage
2088 // -----------------------------------------------------------------------
2090 wxPGAttributeStorage::wxPGAttributeStorage()
2094 wxPGAttributeStorage::~wxPGAttributeStorage()
2096 wxPGHashMapS2P::iterator it
;
2098 for ( it
= m_map
.begin(); it
!= m_map
.end(); it
++ )
2100 wxVariantData
* data
= (wxVariantData
*) it
->second
;
2105 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value
)
2107 wxVariantData
* data
= value
.GetData();
2110 wxPGHashMapS2P::iterator it
= m_map
.find(name
);
2111 if ( it
!= m_map
.end() )
2112 ((wxVariantData
*)it
->second
)->DecRef();
2120 #endif // wxUSE_PROPGRID