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"
34 #include "wx/settings.h"
38 #include "wx/propgrid/propgrid.h"
41 #define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's
44 #define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing
46 #if wxPG_COMPATIBILITY_1_4
48 // Used to establish backwards compatiblity
49 const char* g_invalidStringContent
= "@__TOTALLY_INVALID_STRING__@";
53 // -----------------------------------------------------------------------
55 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect
)
57 #if defined(__WXMSW__) && !defined(__WXWINCE__)
58 // FIXME: Use DrawFocusRect code above (currently it draws solid line
59 // for caption focus but works ok for other stuff).
60 // Also, it seems that this code may not work in future wx versions.
61 dc
.SetLogicalFunction(wxINVERT
);
63 wxPen
pen(*wxBLACK
,1,wxDOT
);
64 pen
.SetCap(wxCAP_BUTT
);
66 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
68 dc
.DrawRectangle(rect
);
70 dc
.SetLogicalFunction(wxCOPY
);
72 dc
.SetLogicalFunction(wxINVERT
);
74 dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
));
75 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
77 dc
.DrawRectangle(rect
);
79 dc
.SetLogicalFunction(wxCOPY
);
83 // -----------------------------------------------------------------------
85 // -----------------------------------------------------------------------
87 wxSize
wxPGCellRenderer::GetImageSize( const wxPGProperty
* WXUNUSED(property
),
89 int WXUNUSED(item
) ) const
94 void wxPGCellRenderer::DrawText( wxDC
& dc
, const wxRect
& rect
,
95 int xOffset
, const wxString
& text
) const
98 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
100 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
101 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
104 void wxPGCellRenderer::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
105 int xOffset
, const wxString
& text
,
106 wxPGProperty
* property
,
107 const wxPGEditor
* editor
) const
110 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
112 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
119 rect2
.height
-= yOffset
;
120 editor
->DrawValue( dc
, rect2
, property
, text
);
125 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
130 void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
132 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
133 wxPGDrawFocusRect(dc
,focusRect
);
136 int wxPGCellRenderer::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
140 if ( !(flags
& Selected
) )
142 // Draw using wxPGCell information, if available
143 wxColour fgCol
= cell
.GetFgCol();
145 dc
.SetTextForeground(fgCol
);
147 wxColour bgCol
= cell
.GetBgCol();
152 dc
.DrawRectangle(rect
);
156 const wxBitmap
& bmp
= cell
.GetBitmap();
158 // In control, do not draw oversized bitmap
159 (!(flags
& Control
) || bmp
.GetHeight() < rect
.height
)
163 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
164 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
166 imageOffset
= bmp
.GetWidth();
172 // -----------------------------------------------------------------------
173 // wxPGDefaultRenderer
174 // -----------------------------------------------------------------------
176 void wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
,
177 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
178 int column
, int item
, int flags
) const
180 bool isUnspecified
= property
->IsValueUnspecified();
182 if ( column
== 1 && item
== -1 )
184 int cmnVal
= property
->GetCommonValue();
188 if ( !isUnspecified
)
189 DrawText( dc
, rect
, 0, propertyGrid
->GetCommonValueLabel(cmnVal
) );
194 const wxPGEditor
* editor
= NULL
;
195 const wxPGCell
* cell
= property
->GetCell(column
);
201 if ( column
== 1 && (flags
& Control
) )
203 int selectedIndex
= property
->GetChoiceSelection();
204 if ( selectedIndex
!= wxNOT_FOUND
)
206 const wxPGChoices
& choices
= property
->GetChoices();
207 const wxPGCell
* ccell
= &choices
[selectedIndex
];
209 ( ccell
->GetBitmap().IsOk() || ccell
->GetFgCol().IsOk() || ccell
->GetBgCol().IsOk() )
217 int preDrawFlags
= flags
;
219 if ( propertyGrid
->GetInternalFlags() & wxPG_FL_CELL_OVERRIDES_SEL
)
220 preDrawFlags
= preDrawFlags
& ~(Selected
);
222 imageOffset
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
223 text
= cell
->GetText();
224 if ( text
== wxS("@!") )
227 text
= property
->GetLabel();
228 else if ( column
== 1 )
229 text
= property
->GetValueAsString();
231 text
= wxEmptyString
;
234 else if ( column
== 0 )
237 DrawText( dc
, rect
, 0, property
->GetLabel() );
239 else if ( column
== 1 )
241 if ( !isUnspecified
)
243 editor
= property
->GetColumnEditor(column
);
245 // Regular property value
247 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
249 wxPGPaintData paintdata
;
250 paintdata
.m_parent
= propertyGrid
;
251 paintdata
.m_choiceItem
= item
;
253 if ( imageSize
.x
> 0 )
255 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
256 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
257 wxPG_CUSTOM_IMAGE_WIDTH
,
258 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
260 /*if ( imageSize.x == wxPG_FULL_CUSTOM_PAINT_WIDTH )
262 imageRect.width = m_width - imageRect.x;
265 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
267 paintdata
.m_drawnWidth
= imageSize
.x
;
268 paintdata
.m_drawnHeight
= imageSize
.y
;
270 if ( !isUnspecified
)
272 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
276 dc
.SetBrush(*wxWHITE_BRUSH
);
277 dc
.DrawRectangle(imageRect
);
280 imageOffset
= paintdata
.m_drawnWidth
;
283 text
= property
->GetValueAsString();
286 if ( propertyGrid
->GetColumnCount() <= 2 )
288 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
289 if ( unitsString
.length() )
290 text
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
294 if ( text
.length() == 0 )
296 // Try to show inline help if no text
297 wxVariant vInlineHelp
= property
->GetAttribute(wxPGGlobalVars
->m_strInlineHelp
);
298 if ( !vInlineHelp
.IsNull() )
300 text
= vInlineHelp
.GetString();
301 dc
.SetTextForeground(propertyGrid
->GetCellDisabledTextColour());
305 else if ( column
== 2 )
308 if ( !text
.length() )
309 text
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
312 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
314 // active caption gets nice dotted rectangle
315 if ( property
->IsCategory() /*&& column == 0*/ )
317 if ( flags
& Selected
)
319 if ( imageOffset
> 0 )
320 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
322 DrawCaptionSelectionRect( dc
,
323 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
324 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
325 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
326 propertyGrid
->GetCaptionFont())
327 +(wxPG_CAPRECTXMARGIN
*2),
328 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
333 wxSize
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
,
337 if ( property
&& column
== 1 )
341 wxBitmap
* bmp
= property
->GetValueImage();
343 if ( bmp
&& bmp
->Ok() )
344 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
350 // -----------------------------------------------------------------------
352 // -----------------------------------------------------------------------
358 wxPGCell::wxPGCell( const wxString
& text
,
359 const wxBitmap
& bitmap
,
360 const wxColour
& fgCol
,
361 const wxColour
& bgCol
)
362 : m_bitmap(bitmap
), m_fgCol(fgCol
), m_bgCol(bgCol
)
367 // -----------------------------------------------------------------------
369 // -----------------------------------------------------------------------
371 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
373 wxString
* wxPGProperty::sm_wxPG_LABEL
= NULL
;
375 void wxPGProperty::Init()
381 m_parentState
= (wxPropertyGridPageState
*) NULL
;
384 m_clientObject
= NULL
;
386 m_customEditor
= (wxPGEditor
*) NULL
;
388 m_validator
= (wxValidator
*) NULL
;
390 m_valueBitmap
= (wxBitmap
*) NULL
;
392 m_maxLen
= 0; // infinite maximum length
394 m_flags
= wxPG_PROP_PROPERTY
;
404 void wxPGProperty::Init( const wxString
& label
, const wxString
& name
)
406 // We really need to check if &label and &name are NULL pointers
407 // (this can if we are called before property grid has been initalized)
409 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
412 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
415 DoSetName( m_label
);
420 void wxPGProperty::InitAfterAdded( wxPropertyGridPageState
* pageState
,
421 wxPropertyGrid
* propgrid
)
424 // Called after property has been added to grid or page
425 // (so propgrid can be NULL, too).
427 wxPGProperty
* parent
= m_parent
;
428 bool parentIsRoot
= parent
->IsKindOf(CLASSINFO(wxPGRootProperty
));
430 m_parentState
= pageState
;
432 #if wxPG_COMPATIBILITY_1_4
433 // Make sure deprecated virtual functions are not implemented
434 wxString s
= GetValueAsString( 0xFFFF );
435 wxASSERT_MSG( s
== g_invalidStringContent
,
436 "Implement ValueToString() instead of GetValueAsString()" );
441 m_bgColIndex
= parent
->m_bgColIndex
;
442 m_fgColIndex
= parent
->m_fgColIndex
;
445 // If in hideable adding mode, or if assigned parent is hideable, then
446 // make this one hideable.
448 ( !parentIsRoot
&& parent
->HasFlag(wxPG_PROP_HIDDEN
) ) ||
449 ( propgrid
&& (propgrid
->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES
)) )
451 SetFlag( wxPG_PROP_HIDDEN
);
453 // Set custom image flag.
454 int custImgHeight
= OnMeasureImage().y
;
455 if ( custImgHeight
< 0 )
457 SetFlag(wxPG_PROP_CUSTOMIMAGE
);
460 if ( propgrid
&& (propgrid
->HasFlag(wxPG_LIMITED_EDITING
)) )
461 SetFlag(wxPG_PROP_NOEDITOR
);
463 // Make sure parent has some parental flags
464 if ( !parent
->HasFlag(wxPG_PROP_PARENTAL_FLAGS
) )
465 parent
->SetParentalType(wxPG_PROP_MISC_PARENT
);
469 // This is not a category.
473 unsigned char depth
= 1;
476 depth
= parent
->m_depth
;
477 if ( !parent
->IsCategory() )
481 unsigned char greyDepth
= depth
;
485 wxPropertyCategory
* pc
;
487 if ( parent
->IsCategory() )
488 pc
= (wxPropertyCategory
* ) parent
;
490 // This conditional compile is necessary to
491 // bypass some compiler bug.
492 pc
= pageState
->GetPropertyCategory(parent
);
495 greyDepth
= pc
->GetDepth();
497 greyDepth
= parent
->m_depthBgCol
;
500 m_depthBgCol
= greyDepth
;
504 // This is a category.
507 unsigned char depth
= 1;
510 depth
= parent
->m_depth
+ 1;
513 m_depthBgCol
= depth
;
517 // Has initial children
518 if ( GetChildCount() )
520 FlagType parentalFlags
= m_flags
& wxPG_PROP_PARENTAL_FLAGS
;
522 // Check parental flags
523 wxASSERT_MSG( parentalFlags
,
524 "Call SetFlag(wxPG_PROP_MISC_PARENT) or"
525 "SetFlag(wxPG_PROP_AGGREGATE) before calling"
526 "wxPGProperty::AddChild()." );
528 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
530 // Properties with private children are not expanded by default.
533 else if ( propgrid
&& propgrid
->HasFlag(wxPG_HIDE_MARGIN
) )
535 // ...unless it cannot be expanded by user and therefore must
536 // remain visible at all times
541 // Prepare children recursively
542 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
544 wxPGProperty
* child
= Item(i
);
545 child
->InitAfterAdded(pageState
, pageState
->GetGrid());
548 if ( propgrid
&& (propgrid
->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES
) )
549 SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED
, true);
553 wxPGProperty::wxPGProperty()
560 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name
)
567 wxPGProperty::~wxPGProperty()
569 delete m_clientObject
;
571 Empty(); // this deletes items
573 delete m_valueBitmap
;
580 for ( i
=0; i
<m_cells
.size(); i
++ )
581 delete (wxPGCell
*) m_cells
[i
];
583 // This makes it easier for us to detect dangling pointers
588 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate
) const
590 wxPGProperty
* parent
= m_parent
;
593 if ( parent
== candidate
)
595 parent
= parent
->m_parent
;
601 wxString
wxPGProperty::GetName() const
603 wxPGProperty
* parent
= GetParent();
605 if ( !m_name
.length() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
608 return m_parent
->GetName() + wxS(".") + m_name
;
611 wxPropertyGrid
* wxPGProperty::GetGrid() const
613 if ( !m_parentState
)
615 return m_parentState
->GetGrid();
618 int wxPGProperty::Index( const wxPGProperty
* p
) const
620 for ( unsigned int i
= 0; i
<m_children
.size(); i
++ )
622 if ( p
== m_children
[i
] )
628 void wxPGProperty::UpdateControl( wxWindow
* primary
)
631 GetEditorClass()->UpdateControl(this, primary
);
634 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
639 void wxPGProperty::OnSetValue()
643 void wxPGProperty::RefreshChildren ()
647 wxString
wxPGProperty::GetColumnText( unsigned int col
) const
649 wxPGCell
* cell
= GetCell(col
);
652 return cell
->GetText();
659 return GetDisplayedString();
661 return GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
664 return wxEmptyString
;
667 void wxPGProperty::DoGenerateComposedValue( wxString
& text
,
669 const wxVariantList
* valueOverrides
,
670 wxPGHashMapS2S
* childResults
) const
673 int iMax
= m_children
.size();
679 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
680 !(argFlags
& wxPG_FULL_VALUE
) )
681 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
683 int iMaxMinusOne
= iMax
-1;
685 if ( !IsTextEditable() )
686 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
688 wxPGProperty
* curChild
= m_children
[0];
690 bool overridesLeft
= false;
691 wxVariant overrideValue
;
692 wxVariantList::const_iterator node
;
694 if ( valueOverrides
)
696 node
= valueOverrides
->begin();
697 if ( node
!= valueOverrides
->end() )
699 overrideValue
= *node
;
700 overridesLeft
= true;
704 for ( i
= 0; i
< iMax
; i
++ )
706 wxVariant childValue
;
708 wxString childLabel
= curChild
->GetLabel();
710 // Check for value override
711 if ( overridesLeft
&& overrideValue
.GetName() == childLabel
)
713 if ( !overrideValue
.IsNull() )
714 childValue
= overrideValue
;
716 childValue
= curChild
->GetValue();
718 if ( node
!= valueOverrides
->end() )
719 overrideValue
= *node
;
721 overridesLeft
= false;
725 childValue
= curChild
->GetValue();
729 if ( !childValue
.IsNull() )
731 if ( overridesLeft
&&
732 curChild
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
733 childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
735 wxVariantList
& childList
= childValue
.GetList();
736 DoGenerateComposedValue(s
, argFlags
|wxPG_COMPOSITE_FRAGMENT
,
737 &childList
, childResults
);
741 s
= curChild
->ValueToString(childValue
,
742 argFlags
|wxPG_COMPOSITE_FRAGMENT
);
746 if ( childResults
&& curChild
->GetChildCount() )
747 (*childResults
)[curChild
->GetName()] = s
;
750 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() )
753 if ( !curChild
->GetChildCount() || skip
)
756 text
+= wxS("[") + s
+ wxS("]");
758 if ( i
< iMaxMinusOne
)
760 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
761 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
762 !(argFlags
& wxPG_FULL_VALUE
) )
767 if ( !curChild
->GetChildCount() )
773 curChild
= m_children
[i
+1];
777 // Remove superfluous semicolon and space
779 if ( text
.EndsWith(wxS("; "), &rest
) )
782 if ( (unsigned int)i
< m_children
.size() )
783 text
+= wxS("; ...");
786 wxString
wxPGProperty::ValueToString( wxVariant
& WXUNUSED(value
),
789 wxCHECK_MSG( GetChildCount() > 0,
791 "If user property does not have any children, it must "
792 "override GetValueAsString" );
794 // FIXME: Currently code below only works if value is actually m_value
795 wxASSERT_MSG( argFlags
& wxPG_VALUE_IS_CURRENT
,
796 "Sorry, currently default wxPGProperty::ValueToString() "
797 "implementation only works if value is m_value." );
800 DoGenerateComposedValue(text
, argFlags
);
804 wxString
wxPGProperty::GetValueAsString( int argFlags
) const
806 #if wxPG_COMPATIBILITY_1_4
807 // This is backwards compatibility test
808 // That is, to make sure this function is not overridden
809 // (instead, ValueToString() should be).
810 if ( argFlags
== 0xFFFF )
812 // Do not override! (for backwards compliancy)
813 return g_invalidStringContent
;
817 if ( IsValueUnspecified() )
818 return wxEmptyString
;
820 if ( m_commonValue
== -1 )
822 wxVariant
value(GetValue());
823 return ValueToString(value
, argFlags
|wxPG_VALUE_IS_CURRENT
);
827 // Return common value's string representation
828 wxPropertyGrid
* pg
= GetGrid();
829 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
831 if ( argFlags
& wxPG_FULL_VALUE
)
833 return cv
->GetLabel();
835 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
837 return cv
->GetEditableText();
841 return cv
->GetLabel();
845 wxString
wxPGProperty::GetValueString( int argFlags
) const
847 return GetValueAsString(argFlags
);
850 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
852 variant
= (long)number
;
856 // Convert semicolon delimited tokens into child values.
857 bool wxPGProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
859 if ( !GetChildCount() )
862 unsigned int curChild
= 0;
864 unsigned int iMax
= m_children
.size();
866 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
867 !(argFlags
& wxPG_FULL_VALUE
) )
868 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
870 bool changed
= false;
875 // Its best only to add non-empty group items
876 bool addOnlyIfNotEmpty
= false;
877 const wxChar delimeter
= wxS(';');
879 size_t tokenStart
= 0xFFFFFF;
881 wxVariantList temp_list
;
882 wxVariant
list(temp_list
);
884 int propagatedFlags
= argFlags
& (wxPG_REPORT_ERROR
|wxPG_PROGRAMMATIC_VALUE
);
887 bool debug_print
= false;
892 wxLogDebug(wxT(">> %s.StringToValue('%s')"),GetLabel().c_str(),text
.c_str());
895 wxString::const_iterator it
= text
.begin();
898 if ( it
!= text
.end() )
905 if ( tokenStart
!= 0xFFFFFF )
908 if ( a
== delimeter
|| a
== 0 )
910 token
= text
.substr(tokenStart
,pos
-tokenStart
);
912 size_t len
= token
.length();
914 if ( !addOnlyIfNotEmpty
|| len
> 0 )
916 const wxPGProperty
* child
= Item(curChild
);
917 wxVariant
variant(child
->GetValue());
918 variant
.SetName(child
->GetBaseName());
922 wxLogDebug(wxT("token = '%s', child = %s"),token
.c_str(),child
->GetLabel().c_str());
925 // Add only if editable or setting programmatically
926 if ( (argFlags
& wxPG_PROGRAMMATIC_VALUE
) ||
927 !child
->HasFlag(wxPG_PROP_DISABLED
|wxPG_PROP_READONLY
) )
931 bool wasUnspecified
= child
->IsValueUnspecified();
933 if ( child
->StringToValue(variant
, token
, propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
935 // Clear unspecified flag only if OnSetValue() didn't
937 if ( child
->IsValueUnspecified() &&
938 (wasUnspecified
|| !UsesAutoUnspecified()) )
940 variant
= child
->GetDefaultValue();
943 list
.Append(variant
);
950 // Empty, becomes unspecified
952 list
.Append(variant
);
958 if ( curChild
>= iMax
)
962 tokenStart
= 0xFFFFFF;
967 // Token is not running
971 addOnlyIfNotEmpty
= false;
973 // Is this a group of tokens?
978 if ( it
!= text
.end() ) it
++;
980 size_t startPos
= pos
;
982 // Group item - find end
983 while ( it
!= text
.end() && depth
> 0 )
991 else if ( a
== wxS('[') )
995 token
= text
.substr(startPos
,pos
-startPos
-1);
997 if ( !token
.length() )
1000 const wxPGProperty
* child
= Item(curChild
);
1002 wxVariant oldChildValue
= child
->GetValue();
1003 wxVariant
variant(oldChildValue
);
1005 if ( (argFlags
& wxPG_PROGRAMMATIC_VALUE
) ||
1006 !child
->HasFlag(wxPG_PROP_DISABLED
|wxPG_PROP_READONLY
) )
1008 bool stvRes
= child
->StringToValue( variant
, token
, propagatedFlags
);
1009 if ( stvRes
|| (variant
!= oldChildValue
) )
1016 // Failed, becomes unspecified
1022 variant
.SetName(child
->GetBaseName());
1023 list
.Append(variant
);
1026 if ( curChild
>= iMax
)
1029 addOnlyIfNotEmpty
= true;
1031 tokenStart
= 0xFFFFFF;
1037 if ( a
== delimeter
)
1050 if ( it
!= text
.end() )
1067 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags
)
1069 wxVariant
variant(m_value
);
1070 bool res
= StringToValue(variant
, text
, argFlags
);
1076 bool wxPGProperty::SetValueFromInt( long number
, int argFlags
)
1078 wxVariant
variant(m_value
);
1079 bool res
= IntToValue(variant
, number
, argFlags
);
1085 wxSize
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const
1087 if ( m_valueBitmap
)
1088 return wxSize(m_valueBitmap
->GetWidth(),-1);
1093 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const
1095 return wxPGGlobalVars
->m_defaultRenderer
;
1098 void wxPGProperty::OnCustomPaint( wxDC
& dc
,
1102 wxBitmap
* bmp
= m_valueBitmap
;
1104 wxCHECK_RET( bmp
&& bmp
->Ok(), wxT("invalid bitmap") );
1106 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
1108 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
1111 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const
1113 return wxPGEditor_TextCtrl
;
1116 // Default extra property event handling - that is, none at all.
1117 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
1123 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
1125 // If auto unspecified values are not wanted (via window or property style),
1126 // then get default value instead of wxNullVariant.
1127 if ( value
.IsNull() && (flags
& wxPG_SETVAL_BY_USER
) &&
1128 !UsesAutoUnspecified() )
1130 value
= GetDefaultValue();
1133 if ( !value
.IsNull() )
1135 wxVariant tempListVariant
;
1138 // List variants are reserved a special purpose
1139 // as intermediate containers for child values
1140 // of properties with children.
1141 if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1144 // However, situation is different for composed string properties
1145 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
1147 tempListVariant
= value
;
1148 pList
= &tempListVariant
;
1152 AdaptListToValue(value
, &newValue
);
1154 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
1157 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
1158 flags
|= wxPG_SETVAL_AGGREGATED
;
1160 if ( pList
&& !pList
->IsNull() )
1162 wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST
);
1163 wxASSERT( GetChildCount() );
1164 wxASSERT( !IsCategory() );
1166 wxVariantList
& list
= pList
->GetList();
1167 wxVariantList::iterator node
;
1170 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
1172 // Children in list can be in any order, but we will give hint to
1173 // GetPropertyByNameWH(). This optimizes for full list parsing.
1174 for ( node
= list
.begin(); node
!= list
.end(); node
++ )
1176 wxVariant
& childValue
= *((wxVariant
*)*node
);
1177 wxPGProperty
* child
= GetPropertyByNameWH(childValue
.GetName(), i
);
1180 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
1181 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1183 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
1185 wxVariant listRefCopy
= childValue
;
1186 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
1190 wxVariant oldVal
= child
->GetValue();
1191 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
1194 else if ( child
->GetValue() != childValue
)
1196 // For aggregate properties, we will trust RefreshChildren()
1197 // to update child values.
1198 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
1199 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1200 if ( flags
& wxPG_SETVAL_BY_USER
)
1201 child
->SetFlag(wxPG_PROP_MODIFIED
);
1208 if ( !value
.IsNull() )
1213 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
1214 UpdateParentValues();
1217 if ( flags
& wxPG_SETVAL_BY_USER
)
1218 SetFlag(wxPG_PROP_MODIFIED
);
1220 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1225 if ( m_commonValue
!= -1 )
1227 wxPropertyGrid
* pg
= GetGrid();
1228 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
1234 // Set children to unspecified, but only if aggregate or
1235 // value is <composed>
1236 if ( AreChildrenComponents() )
1239 for ( i
=0; i
<GetChildCount(); i
++ )
1240 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1245 // Update editor control
1248 // We need to check for these, otherwise GetGrid() may fail.
1249 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1254 void wxPGProperty::SetValueInEvent( wxVariant value
) const
1256 GetGrid()->ValueChangeInEvent(value
);
1259 void wxPGProperty::SetFlagRecursively( FlagType flag
, bool set
)
1267 for ( i
= 0; i
< GetChildCount(); i
++ )
1268 Item(i
)->SetFlagRecursively(flag
, set
);
1271 void wxPGProperty::RefreshEditor()
1273 if ( m_parent
&& GetParentState() )
1275 wxPropertyGrid
* pg
= GetParentState()->GetGrid();
1276 if ( pg
->GetSelectedProperty() == this )
1278 wxWindow
* editor
= pg
->GetEditorControl();
1280 GetEditorClass()->UpdateControl( this, editor
);
1286 wxVariant
wxPGProperty::GetDefaultValue() const
1288 wxVariant defVal
= GetAttribute(wxS("DefaultValue"));
1289 if ( !defVal
.IsNull() )
1292 wxVariant value
= GetValue();
1294 if ( !value
.IsNull() )
1296 wxString
valueType(value
.GetType());
1298 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1299 return wxPGVariant_Zero
;
1300 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1301 return wxPGVariant_EmptyString
;
1302 if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1303 return wxPGVariant_False
;
1304 if ( valueType
== wxPG_VARIANT_TYPE_DOUBLE
)
1305 return wxVariant(0.0);
1306 if ( valueType
== wxPG_VARIANT_TYPE_ARRSTRING
)
1307 return wxVariant(wxArrayString());
1308 if ( valueType
== wxS("wxLongLong") )
1309 return WXVARIANT(wxLongLong(0));
1310 if ( valueType
== wxS("wxULongLong") )
1311 return WXVARIANT(wxULongLong(0));
1312 if ( valueType
== wxS("wxColour") )
1313 return WXVARIANT(*wxBLACK
);
1315 if ( valueType
== wxPG_VARIANT_TYPE_DATETIME
)
1316 return wxVariant(wxDateTime::Now());
1318 if ( valueType
== wxS("wxFont") )
1319 return WXVARIANT(*wxNORMAL_FONT
);
1320 if ( valueType
== wxS("wxPoint") )
1321 return WXVARIANT(wxPoint(0, 0));
1322 if ( valueType
== wxS("wxSize") )
1323 return WXVARIANT(wxSize(0, 0));
1329 void wxPGProperty::SetCell( int column
, wxPGCell
* cellObj
)
1331 if ( column
>= (int)m_cells
.size() )
1332 m_cells
.SetCount(column
+1, NULL
);
1334 delete (wxPGCell
*) m_cells
[column
];
1335 m_cells
[column
] = cellObj
;
1338 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const
1343 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1348 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value
)
1350 if ( DoSetAttribute( name
, value
) )
1352 // Support working without grid, when possible
1353 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1357 m_attributes
.Set( name
, value
);
1360 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes
)
1362 wxPGAttributeStorage::const_iterator it
= attributes
.StartIteration();
1365 while ( attributes
.GetNext(it
, variant
) )
1366 SetAttribute( variant
.GetName(), variant
);
1369 wxVariant
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1375 wxVariant
wxPGProperty::GetAttribute( const wxString
& name
) const
1377 return m_attributes
.FindValue(name
);
1380 wxString
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1382 wxVariant variant
= m_attributes
.FindValue(name
);
1384 if ( !variant
.IsNull() )
1385 return variant
.GetString();
1390 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1392 wxVariant variant
= m_attributes
.FindValue(name
);
1394 return wxPGVariantToInt(variant
, defVal
);
1397 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1400 wxVariant variant
= m_attributes
.FindValue(name
);
1402 if ( wxPGVariantToDouble(variant
, &retVal
) )
1408 wxVariant
wxPGProperty::GetAttributesAsList() const
1410 wxVariantList tempList
;
1411 wxVariant
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) );
1413 wxPGAttributeStorage::const_iterator it
= m_attributes
.StartIteration();
1416 while ( m_attributes
.GetNext(it
, variant
) )
1422 // Slots of utility flags are NULL
1423 const unsigned int gs_propFlagToStringSize
= 14;
1425 static const wxChar
* gs_propFlagToString
[gs_propFlagToStringSize
] = {
1442 wxString
wxPGProperty::GetFlagsAsString( FlagType flagsMask
) const
1445 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1449 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1451 if ( relevantFlags
& a
)
1453 const wxChar
* fs
= gs_propFlagToString
[i
];
1465 void wxPGProperty::SetFlagsFromString( const wxString
& str
)
1469 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1471 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1473 const wxChar
* fs
= gs_propFlagToString
[i
];
1474 if ( fs
&& str
== fs
)
1480 WX_PG_TOKENIZER1_END()
1482 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1485 wxValidator
* wxPGProperty::DoGetValidator() const
1487 return (wxValidator
*) NULL
;
1490 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value
)
1492 wxPropertyGrid
* pg
= GetGrid();
1493 int sel
= GetChoiceSelection();
1497 if ( index
== wxNOT_FOUND
)
1498 index
= m_choices
.GetCount();
1503 m_choices
.Insert(label
, index
, value
);
1505 if ( sel
!= newSel
)
1506 SetChoiceSelection(newSel
);
1508 if ( this == pg
->GetSelection() )
1509 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1515 void wxPGProperty::DeleteChoice( int index
)
1517 wxPropertyGrid
* pg
= GetGrid();
1519 int sel
= GetChoiceSelection();
1522 // Adjust current value
1525 SetValueToUnspecified();
1528 else if ( index
< sel
)
1533 m_choices
.RemoveAt(index
);
1535 if ( sel
!= newSel
)
1536 SetChoiceSelection(newSel
);
1538 if ( this == pg
->GetSelection() )
1539 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1542 int wxPGProperty::GetChoiceSelection() const
1544 wxVariant value
= GetValue();
1545 wxString valueType
= value
.GetType();
1546 int index
= wxNOT_FOUND
;
1548 if ( IsValueUnspecified() || !m_choices
.GetCount() )
1551 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1553 index
= value
.GetLong();
1555 else if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1557 index
= m_choices
.Index(value
.GetString());
1559 else if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1561 index
= value
.GetBool()? 1 : 0;
1567 void wxPGProperty::SetChoiceSelection( int newValue
)
1569 // Changes value of a property with choices, but only
1570 // works if the value type is long or string.
1571 wxString valueType
= GetValue().GetType();
1573 wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") );
1575 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1577 SetValue( m_choices
.GetLabel(newValue
) );
1579 else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
1581 SetValue( (long) newValue
);
1585 bool wxPGProperty::SetChoices( wxPGChoices
& choices
)
1587 m_choices
.Assign(choices
);
1590 // This may be needed to trigger some initialization
1591 // (but don't do it if property is somewhat uninitialized)
1592 wxVariant defVal
= GetDefaultValue();
1593 if ( defVal
.IsNull() )
1603 const wxPGEditor
* wxPGProperty::GetEditorClass() const
1605 const wxPGEditor
* editor
;
1607 if ( !m_customEditor
)
1609 editor
= DoGetEditorClass();
1612 editor
= m_customEditor
;
1615 // Maybe override editor if common value specified
1616 if ( GetDisplayedCommonValueCount() )
1618 // TextCtrlAndButton -> ComboBoxAndButton
1619 if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) )
1620 editor
= wxPGEditor_ChoiceAndButton
;
1622 // TextCtrl -> ComboBox
1623 else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) )
1624 editor
= wxPGEditor_ComboBox
;
1630 bool wxPGProperty::HasVisibleChildren() const
1634 for ( i
=0; i
<GetChildCount(); i
++ )
1636 wxPGProperty
* child
= Item(i
);
1638 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
1645 bool wxPGProperty::RecreateEditor()
1647 wxPropertyGrid
* pg
= GetGrid();
1650 wxPGProperty
* selected
= pg
->GetSelection();
1651 if ( this == selected
)
1653 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
1660 void wxPGProperty::SetValueImage( wxBitmap
& bmp
)
1662 delete m_valueBitmap
;
1664 if ( &bmp
&& bmp
.Ok() )
1667 wxSize maxSz
= GetGrid()->GetImageSize();
1668 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
1670 if ( imSz
.x
!= maxSz
.x
|| imSz
.y
!= maxSz
.y
)
1672 // Create a memory DC
1673 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
1676 dc
.SelectObject(*bmpNew
);
1679 // FIXME: This is ugly - use image or wait for scaling patch.
1680 double scaleX
= (double)maxSz
.x
/ (double)imSz
.x
;
1681 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
1683 dc
.SetUserScale(scaleX
,scaleY
);
1685 dc
.DrawBitmap( bmp
, 0, 0 );
1687 m_valueBitmap
= bmpNew
;
1691 m_valueBitmap
= new wxBitmap(bmp
);
1694 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1698 m_valueBitmap
= NULL
;
1699 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
1704 wxPGProperty
* wxPGProperty::GetMainParent() const
1706 const wxPGProperty
* curChild
= this;
1707 const wxPGProperty
* curParent
= m_parent
;
1709 while ( curParent
&& !curParent
->IsCategory() )
1711 curChild
= curParent
;
1712 curParent
= curParent
->m_parent
;
1715 return (wxPGProperty
*) curChild
;
1719 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const
1722 // Returns last visible sub-item, recursively.
1723 if ( !IsExpanded() || !GetChildCount() )
1726 return Last()->GetLastVisibleSubItem();
1730 bool wxPGProperty::IsVisible() const
1732 const wxPGProperty
* parent
;
1734 if ( HasFlag(wxPG_PROP_HIDDEN
) )
1737 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
1739 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
1746 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const
1748 wxPropertyGridPageState
* state
= GetParentState();
1749 wxPropertyGrid
* propGrid
= state
->GetGrid();
1750 if ( state
== propGrid
->GetState() )
1756 int wxPGProperty::GetY2( int lh
) const
1758 const wxPGProperty
* parent
;
1759 const wxPGProperty
* child
= this;
1763 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
1765 if ( !parent
->IsExpanded() )
1767 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
1772 y
-= lh
; // need to reduce one level
1778 int wxPGProperty::GetY() const
1780 return GetY2(GetGrid()->GetRowHeight());
1783 // This is used by Insert etc.
1784 void wxPGProperty::AddChild2( wxPGProperty
* prop
, int index
, bool correct_mode
)
1786 if ( index
< 0 || (size_t)index
>= m_children
.size() )
1788 if ( correct_mode
) prop
->m_arrIndex
= m_children
.size();
1789 m_children
.push_back( prop
);
1793 m_children
.insert( m_children
.begin()+index
, prop
);
1794 if ( correct_mode
) FixIndicesOfChildren( index
);
1797 prop
->m_parent
= this;
1800 // This is used by properties that have fixed sub-properties
1801 void wxPGProperty::AddChild( wxPGProperty
* prop
)
1803 wxASSERT_MSG( prop
->GetBaseName().length(),
1804 "Property's children must have unique, non-empty names within their scope" );
1806 prop
->m_arrIndex
= m_children
.size();
1807 m_children
.push_back( prop
);
1809 int custImgHeight
= prop
->OnMeasureImage().y
;
1810 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
1811 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1813 prop
->m_parent
= this;
1816 void wxPGProperty::RemoveChild( wxPGProperty
* p
)
1818 wxArrayPGProperty::iterator it
;
1819 wxArrayPGProperty
& children
= m_children
;
1821 for ( it
=children
.begin(); it
!= children
.end(); it
++ )
1825 m_children
.erase(it
);
1831 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
1833 wxASSERT( GetChildCount() );
1834 wxASSERT( !IsCategory() );
1836 *value
= GetValue();
1838 if ( !list
.GetCount() )
1841 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
1843 bool allChildrenSpecified
;
1845 // Don't fully update aggregate properties unless all children have
1847 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1848 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
1850 allChildrenSpecified
= true;
1852 wxVariant childValue
= list
[0];
1856 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
1858 for ( i
=0; i
<GetChildCount(); i
++ )
1860 const wxPGProperty
* child
= Item(i
);
1862 if ( childValue
.GetName() == child
->GetBaseName() )
1864 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
1866 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1868 wxVariant
cv2(child
->GetValue());
1869 child
->AdaptListToValue(childValue
, &cv2
);
1873 if ( allChildrenSpecified
)
1874 ChildChanged(*value
, i
, childValue
);
1876 if ( n
== (unsigned int)list
.GetCount() )
1878 childValue
= list
[n
];
1884 void wxPGProperty::FixIndicesOfChildren( unsigned int starthere
)
1887 for ( i
=starthere
;i
<GetChildCount();i
++)
1888 Item(i
)->m_arrIndex
= i
;
1892 // Returns (direct) child property with given name (or NULL if not found)
1893 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name
) const
1897 for ( i
=0; i
<GetChildCount(); i
++ )
1899 wxPGProperty
* p
= Item(i
);
1900 if ( p
->m_name
== name
)
1904 // Does it have point, then?
1905 int pos
= name
.Find(wxS('.'));
1907 return (wxPGProperty
*) NULL
;
1909 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
1911 if ( !p
|| !p
->GetChildCount() )
1914 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
1917 wxPGProperty
* wxPGProperty::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex
) const
1919 unsigned int i
= hintIndex
;
1921 if ( i
>= GetChildCount() )
1924 unsigned int lastIndex
= i
- 1;
1926 if ( lastIndex
>= GetChildCount() )
1927 lastIndex
= GetChildCount() - 1;
1931 wxPGProperty
* p
= Item(i
);
1932 if ( p
->m_name
== name
)
1935 if ( i
== lastIndex
)
1939 if ( i
== GetChildCount() )
1946 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_
) const
1948 // Returns height of children, recursively, and
1949 // by taking expanded/collapsed status into account.
1951 // iMax is used when finding property y-positions.
1957 iMax_
= GetChildCount();
1959 unsigned int iMax
= iMax_
;
1961 wxASSERT( iMax
<= GetChildCount() );
1963 if ( !IsExpanded() && GetParent() )
1968 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
1970 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1972 if ( !pwc
->IsExpanded() ||
1973 pwc
->GetChildCount() == 0 )
1976 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
1985 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
, unsigned int lh
, unsigned int* nextItemY
) const
1987 wxASSERT( nextItemY
);
1989 // Linear search at the moment
1991 // nextItemY = y of next visible property, final value will be written back.
1992 wxPGProperty
* result
= NULL
;
1993 wxPGProperty
* current
= NULL
;
1994 unsigned int iy
= *nextItemY
;
1996 unsigned int iMax
= GetChildCount();
2000 wxPGProperty
* pwc
= Item(i
);
2002 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
2013 if ( pwc
->IsExpanded() &&
2014 pwc
->GetChildCount() > 0 )
2016 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
2028 if ( !result
&& y
< iy
)
2035 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
2037 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
2040 return (wxPGProperty
*) result
;
2043 void wxPGProperty::Empty()
2046 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
2048 for ( i
=0; i
<GetChildCount(); i
++ )
2050 delete m_children
[i
];
2057 void wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
2058 int WXUNUSED(childIndex
),
2059 wxVariant
& WXUNUSED(childValue
) ) const
2063 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList
) const
2067 const wxVariantList
* pList
= NULL
;
2068 wxVariantList::const_iterator node
;
2072 pList
= &pendingList
->GetList();
2073 node
= pList
->begin();
2076 for ( i
=0; i
<GetChildCount(); i
++ )
2078 wxPGProperty
* child
= Item(i
);
2079 const wxVariant
* listValue
= NULL
;
2084 const wxString
& childName
= child
->GetBaseName();
2086 for ( ; node
!= pList
->end(); node
++ )
2088 const wxVariant
& item
= *((const wxVariant
*)*node
);
2089 if ( item
.GetName() == childName
)
2099 value
= child
->GetValue();
2101 if ( value
.IsNull() )
2104 // Check recursively
2105 if ( child
->GetChildCount() )
2107 const wxVariant
* childList
= NULL
;
2109 if ( listValue
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST
)
2110 childList
= listValue
;
2112 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
2120 wxPGProperty
* wxPGProperty::UpdateParentValues()
2122 wxPGProperty
* parent
= m_parent
;
2123 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
2124 !parent
->IsCategory() && !parent
->IsRoot() )
2127 parent
->DoGenerateComposedValue(s
);
2128 parent
->m_value
= s
;
2129 return parent
->UpdateParentValues();
2134 bool wxPGProperty::IsTextEditable() const
2136 if ( HasFlag(wxPG_PROP_READONLY
) )
2139 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
2141 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
2148 // Call after fixed sub-properties added/removed after creation.
2149 // if oldSelInd >= 0 and < new max items, then selection is
2150 // moved to it. Note: oldSelInd -2 indicates that this property
2151 // should be selected.
2152 void wxPGProperty::SubPropsChanged( int oldSelInd
)
2154 wxPropertyGridPageState
* state
= GetParentState();
2155 wxPropertyGrid
* grid
= state
->GetGrid();
2158 // Re-repare children (recursively)
2159 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
2161 wxPGProperty
* child
= Item(i
);
2162 child
->InitAfterAdded(state
, grid
);
2165 wxPGProperty
* sel
= (wxPGProperty
*) NULL
;
2166 if ( oldSelInd
>= (int)m_children
.size() )
2167 oldSelInd
= (int)m_children
.size() - 1;
2169 if ( oldSelInd
>= 0 )
2170 sel
= m_children
[oldSelInd
];
2171 else if ( oldSelInd
== -2 )
2175 state
->DoSelectProperty(sel
);
2177 if ( state
== grid
->GetState() )
2179 grid
->GetPanel()->Refresh();
2183 // -----------------------------------------------------------------------
2185 // -----------------------------------------------------------------------
2187 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2188 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2191 wxPGRootProperty::wxPGRootProperty()
2195 m_name
= wxS("<root>");
2202 wxPGRootProperty::~wxPGRootProperty()
2207 // -----------------------------------------------------------------------
2208 // wxPropertyCategory
2209 // -----------------------------------------------------------------------
2211 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2212 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2214 void wxPropertyCategory::Init()
2216 // don't set colour - prepareadditem method should do this
2217 SetParentalType(wxPG_PROP_CATEGORY
);
2218 m_capFgColIndex
= 1;
2222 wxPropertyCategory::wxPropertyCategory()
2229 wxPropertyCategory::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2230 : wxPGProperty(label
,name
)
2236 wxPropertyCategory::~wxPropertyCategory()
2241 wxString
wxPropertyCategory::ValueToString( wxVariant
& WXUNUSED(value
),
2242 int WXUNUSED(argFlags
) ) const
2244 return wxEmptyString
;
2247 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2249 if ( m_textExtent
> 0 )
2250 return m_textExtent
;
2252 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2256 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2259 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2263 // -----------------------------------------------------------------------
2264 // wxPGAttributeStorage
2265 // -----------------------------------------------------------------------
2267 wxPGAttributeStorage::wxPGAttributeStorage()
2271 wxPGAttributeStorage::~wxPGAttributeStorage()
2273 wxPGHashMapS2P::iterator it
;
2275 for ( it
= m_map
.begin(); it
!= m_map
.end(); it
++ )
2277 wxVariantData
* data
= (wxVariantData
*) it
->second
;
2282 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value
)
2284 wxVariantData
* data
= value
.GetData();
2287 wxPGHashMapS2P::iterator it
= m_map
.find(name
);
2288 if ( it
!= m_map
.end() )
2290 ((wxVariantData
*)it
->second
)->DecRef();
2294 // If Null variant, just remove from set
2308 #endif // wxUSE_PROPGRID