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
47 // -----------------------------------------------------------------------
49 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect
)
51 #if defined(__WXMSW__) && !defined(__WXWINCE__)
52 // FIXME: Use DrawFocusRect code above (currently it draws solid line
53 // for caption focus but works ok for other stuff).
54 // Also, it seems that this code may not work in future wx versions.
55 dc
.SetLogicalFunction(wxINVERT
);
57 wxPen
pen(*wxBLACK
,1,wxDOT
);
58 pen
.SetCap(wxCAP_BUTT
);
60 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
62 dc
.DrawRectangle(rect
);
64 dc
.SetLogicalFunction(wxCOPY
);
66 dc
.SetLogicalFunction(wxINVERT
);
68 dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
));
69 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
71 dc
.DrawRectangle(rect
);
73 dc
.SetLogicalFunction(wxCOPY
);
77 // -----------------------------------------------------------------------
79 // -----------------------------------------------------------------------
81 wxSize
wxPGCellRenderer::GetImageSize( const wxPGProperty
* WXUNUSED(property
),
83 int WXUNUSED(item
) ) const
88 void wxPGCellRenderer::DrawText( wxDC
& dc
, const wxRect
& rect
,
89 int xOffset
, const wxString
& text
) const
92 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
94 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
95 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
98 void wxPGCellRenderer::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
99 int xOffset
, const wxString
& text
,
100 wxPGProperty
* property
,
101 const wxPGEditor
* editor
) const
104 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
106 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
113 rect2
.height
-= yOffset
;
114 editor
->DrawValue( dc
, rect2
, property
, text
);
119 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
124 void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
126 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
127 wxPGDrawFocusRect(dc
,focusRect
);
130 int wxPGCellRenderer::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
134 if ( !(flags
& Selected
) )
136 // Draw using wxPGCell information, if available
137 wxColour fgCol
= cell
.GetFgCol();
139 dc
.SetTextForeground(fgCol
);
141 wxColour bgCol
= cell
.GetBgCol();
146 dc
.DrawRectangle(rect
);
150 const wxBitmap
& bmp
= cell
.GetBitmap();
152 // In control, do not draw oversized bitmap
153 (!(flags
& Control
) || bmp
.GetHeight() < rect
.height
)
157 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
158 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
160 imageOffset
= bmp
.GetWidth();
166 // -----------------------------------------------------------------------
167 // wxPGDefaultRenderer
168 // -----------------------------------------------------------------------
170 void wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
,
171 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
172 int column
, int item
, int flags
) const
174 bool isUnspecified
= property
->IsValueUnspecified();
176 if ( column
== 1 && item
== -1 )
178 int cmnVal
= property
->GetCommonValue();
182 if ( !isUnspecified
)
183 DrawText( dc
, rect
, 0, propertyGrid
->GetCommonValueLabel(cmnVal
) );
188 const wxPGEditor
* editor
= NULL
;
189 const wxPGCell
* cell
= property
->GetCell(column
);
195 if ( column
== 1 && (flags
& Control
) )
197 int selectedIndex
= property
->GetChoiceSelection();
198 if ( selectedIndex
!= wxNOT_FOUND
)
200 const wxPGChoices
& choices
= property
->GetChoices();
201 const wxPGCell
* ccell
= &choices
[selectedIndex
];
203 ( ccell
->GetBitmap().IsOk() || ccell
->GetFgCol().IsOk() || ccell
->GetBgCol().IsOk() )
211 int preDrawFlags
= flags
;
213 if ( propertyGrid
->GetInternalFlags() & wxPG_FL_CELL_OVERRIDES_SEL
)
214 preDrawFlags
= preDrawFlags
& ~(Selected
);
216 imageOffset
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
217 text
= cell
->GetText();
218 if ( text
== wxS("@!") )
221 text
= property
->GetLabel();
222 else if ( column
== 1 )
223 text
= property
->GetValueString();
225 text
= wxEmptyString
;
228 else if ( column
== 0 )
231 DrawText( dc
, rect
, 0, property
->GetLabel() );
233 else if ( column
== 1 )
235 if ( !isUnspecified
)
237 editor
= property
->GetColumnEditor(column
);
239 // Regular property value
241 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
243 wxPGPaintData paintdata
;
244 paintdata
.m_parent
= propertyGrid
;
245 paintdata
.m_choiceItem
= item
;
247 if ( imageSize
.x
> 0 )
249 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
250 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
251 wxPG_CUSTOM_IMAGE_WIDTH
,
252 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
254 /*if ( imageSize.x == wxPG_FULL_CUSTOM_PAINT_WIDTH )
256 imageRect.width = m_width - imageRect.x;
259 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
261 paintdata
.m_drawnWidth
= imageSize
.x
;
262 paintdata
.m_drawnHeight
= imageSize
.y
;
264 if ( !isUnspecified
)
266 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
270 dc
.SetBrush(*wxWHITE_BRUSH
);
271 dc
.DrawRectangle(imageRect
);
274 imageOffset
= paintdata
.m_drawnWidth
;
277 text
= property
->GetValueString();
280 if ( propertyGrid
->GetColumnCount() <= 2 )
282 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
283 if ( unitsString
.length() )
284 text
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
288 if ( text
.length() == 0 )
290 // Try to show inline help if no text
291 wxVariant vInlineHelp
= property
->GetAttribute(wxPGGlobalVars
->m_strInlineHelp
);
292 if ( !vInlineHelp
.IsNull() )
294 text
= vInlineHelp
.GetString();
295 dc
.SetTextForeground(propertyGrid
->GetCellDisabledTextColour());
299 else if ( column
== 2 )
302 if ( !text
.length() )
303 text
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
306 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
308 // active caption gets nice dotted rectangle
309 if ( property
->IsCategory() /*&& column == 0*/ )
311 if ( flags
& Selected
)
313 if ( imageOffset
> 0 )
314 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
316 DrawCaptionSelectionRect( dc
,
317 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
318 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
319 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
320 propertyGrid
->GetCaptionFont())
321 +(wxPG_CAPRECTXMARGIN
*2),
322 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
327 wxSize
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
,
331 if ( property
&& column
== 1 )
335 wxBitmap
* bmp
= property
->GetValueImage();
337 if ( bmp
&& bmp
->Ok() )
338 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
344 // -----------------------------------------------------------------------
346 // -----------------------------------------------------------------------
352 wxPGCell::wxPGCell( const wxString
& text
,
353 const wxBitmap
& bitmap
,
354 const wxColour
& fgCol
,
355 const wxColour
& bgCol
)
356 : m_bitmap(bitmap
), m_fgCol(fgCol
), m_bgCol(bgCol
)
361 // -----------------------------------------------------------------------
363 // -----------------------------------------------------------------------
365 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
367 wxString
* wxPGProperty::sm_wxPG_LABEL
= NULL
;
369 void wxPGProperty::Init()
375 m_parentState
= (wxPropertyGridPageState
*) NULL
;
378 m_clientObject
= NULL
;
380 m_customEditor
= (wxPGEditor
*) NULL
;
382 m_validator
= (wxValidator
*) NULL
;
384 m_valueBitmap
= (wxBitmap
*) NULL
;
386 m_maxLen
= 0; // infinite maximum length
388 m_flags
= wxPG_PROP_PROPERTY
;
398 void wxPGProperty::Init( const wxString
& label
, const wxString
& name
)
400 // We really need to check if &label and &name are NULL pointers
401 // (this can if we are called before property grid has been initalized)
403 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
406 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
409 DoSetName( m_label
);
414 void wxPGProperty::InitAfterAdded( wxPropertyGridPageState
* pageState
,
415 wxPropertyGrid
* propgrid
)
418 // Called after property has been added to grid or page
419 // (so propgrid can be NULL, too).
421 wxPGProperty
* parent
= m_parent
;
422 bool parentIsRoot
= parent
->IsKindOf(CLASSINFO(wxPGRootProperty
));
424 m_parentState
= pageState
;
428 m_bgColIndex
= parent
->m_bgColIndex
;
429 m_fgColIndex
= parent
->m_fgColIndex
;
432 // If in hideable adding mode, or if assigned parent is hideable, then
433 // make this one hideable.
435 ( !parentIsRoot
&& parent
->HasFlag(wxPG_PROP_HIDDEN
) ) ||
436 ( propgrid
&& (propgrid
->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES
)) )
438 SetFlag( wxPG_PROP_HIDDEN
);
440 // Set custom image flag.
441 int custImgHeight
= OnMeasureImage().y
;
442 if ( custImgHeight
< 0 )
444 SetFlag(wxPG_PROP_CUSTOMIMAGE
);
447 if ( propgrid
&& (propgrid
->HasFlag(wxPG_LIMITED_EDITING
)) )
448 SetFlag(wxPG_PROP_NOEDITOR
);
450 // Make sure parent has some parental flags
451 if ( !parent
->HasFlag(wxPG_PROP_PARENTAL_FLAGS
) )
452 parent
->SetParentalType(wxPG_PROP_MISC_PARENT
);
456 // This is not a category.
460 unsigned char depth
= 1;
463 depth
= parent
->m_depth
;
464 if ( !parent
->IsCategory() )
468 unsigned char greyDepth
= depth
;
472 wxPropertyCategory
* pc
;
474 if ( parent
->IsCategory() )
475 pc
= (wxPropertyCategory
* ) parent
;
477 // This conditional compile is necessary to
478 // bypass some compiler bug.
479 pc
= pageState
->GetPropertyCategory(parent
);
482 greyDepth
= pc
->GetDepth();
484 greyDepth
= parent
->m_depthBgCol
;
487 m_depthBgCol
= greyDepth
;
491 // This is a category.
494 unsigned char depth
= 1;
497 depth
= parent
->m_depth
+ 1;
500 m_depthBgCol
= depth
;
504 // Has initial children
505 if ( GetChildCount() )
507 FlagType parentalFlags
= m_flags
& wxPG_PROP_PARENTAL_FLAGS
;
509 // Check parental flags
510 wxASSERT_MSG( parentalFlags
,
511 "Call SetFlag(wxPG_PROP_MISC_PARENT) or"
512 "SetFlag(wxPG_PROP_AGGREGATE) before calling"
513 "wxPGProperty::AddChild()." );
515 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
517 // Properties with private children are not expanded by default.
520 else if ( propgrid
&& propgrid
->HasFlag(wxPG_HIDE_MARGIN
) )
522 // ...unless it cannot be expanded by user and therefore must
523 // remain visible at all times
528 // Prepare children recursively
529 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
531 wxPGProperty
* child
= Item(i
);
532 child
->InitAfterAdded(pageState
, pageState
->GetGrid());
535 if ( propgrid
&& (propgrid
->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES
) )
536 SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED
, true);
540 wxPGProperty::wxPGProperty()
547 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name
)
554 wxPGProperty::~wxPGProperty()
556 delete m_clientObject
;
558 Empty(); // this deletes items
560 delete m_valueBitmap
;
567 for ( i
=0; i
<m_cells
.size(); i
++ )
568 delete (wxPGCell
*) m_cells
[i
];
570 // This makes it easier for us to detect dangling pointers
575 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate
) const
577 wxPGProperty
* parent
= m_parent
;
580 if ( parent
== candidate
)
582 parent
= parent
->m_parent
;
588 wxString
wxPGProperty::GetName() const
590 wxPGProperty
* parent
= GetParent();
592 if ( !m_name
.length() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
595 return m_parent
->GetName() + wxS(".") + m_name
;
598 wxPropertyGrid
* wxPGProperty::GetGrid() const
600 if ( !m_parentState
)
602 return m_parentState
->GetGrid();
605 int wxPGProperty::Index( const wxPGProperty
* p
) const
607 for ( unsigned int i
= 0; i
<m_children
.size(); i
++ )
609 if ( p
== m_children
[i
] )
615 void wxPGProperty::UpdateControl( wxWindow
* primary
)
618 GetEditorClass()->UpdateControl(this, primary
);
621 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
626 void wxPGProperty::OnSetValue()
630 void wxPGProperty::RefreshChildren ()
634 wxString
wxPGProperty::GetColumnText( unsigned int col
) const
636 wxPGCell
* cell
= GetCell(col
);
639 return cell
->GetText();
646 return GetDisplayedString();
648 return GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
651 return wxEmptyString
;
654 void wxPGProperty::GenerateComposedValue( wxString
& text
, int argFlags
) const
657 int iMax
= m_children
.size();
663 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
664 !(argFlags
& wxPG_FULL_VALUE
) )
665 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
667 int iMaxMinusOne
= iMax
-1;
669 if ( !IsTextEditable() )
670 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
672 wxPGProperty
* curChild
= m_children
[0];
674 for ( i
= 0; i
< iMax
; i
++ )
677 if ( !curChild
->IsValueUnspecified() )
678 s
= curChild
->GetValueString(argFlags
|wxPG_COMPOSITE_FRAGMENT
);
681 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() )
684 if ( !curChild
->GetChildCount() || skip
)
687 text
+= wxS("[") + s
+ wxS("]");
689 if ( i
< iMaxMinusOne
)
691 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
692 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
693 !(argFlags
& wxPG_FULL_VALUE
) )
698 if ( !curChild
->GetChildCount() )
704 curChild
= m_children
[i
+1];
708 // Remove superfluous semicolon and space
710 if ( text
.EndsWith(wxS("; "), &rest
) )
713 if ( (unsigned int)i
< m_children
.size() )
714 text
+= wxS("; ...");
717 wxString
wxPGProperty::GetValueAsString( int argFlags
) const
719 wxCHECK_MSG( GetChildCount() > 0,
721 wxT("If user property does not have any children, it must override GetValueAsString") );
724 GenerateComposedValue(text
, argFlags
);
728 wxString
wxPGProperty::GetValueString( int argFlags
) const
730 if ( IsValueUnspecified() )
731 return wxEmptyString
;
733 if ( m_commonValue
== -1 )
734 return GetValueAsString(argFlags
);
737 // Return common value's string representation
738 wxPropertyGrid
* pg
= GetGrid();
739 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
741 if ( argFlags
& wxPG_FULL_VALUE
)
743 return cv
->GetLabel();
745 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
747 return cv
->GetEditableText();
751 return cv
->GetLabel();
755 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
757 variant
= (long)number
;
761 // Convert semicolon delimited tokens into child values.
762 bool wxPGProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
764 if ( !GetChildCount() )
767 unsigned int curChild
= 0;
769 unsigned int iMax
= m_children
.size();
771 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
772 !(argFlags
& wxPG_FULL_VALUE
) )
773 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
775 bool changed
= false;
780 // Its best only to add non-empty group items
781 bool addOnlyIfNotEmpty
= false;
782 const wxChar delimeter
= wxS(';');
784 size_t tokenStart
= 0xFFFFFF;
786 wxVariantList temp_list
;
787 wxVariant
list(temp_list
);
789 int propagatedFlags
= argFlags
& wxPG_REPORT_ERROR
;
792 bool debug_print
= false;
797 wxLogDebug(wxT(">> %s.StringToValue('%s')"),GetLabel().c_str(),text
.c_str());
800 wxString::const_iterator it
= text
.begin();
803 if ( it
!= text
.end() )
810 if ( tokenStart
!= 0xFFFFFF )
813 if ( a
== delimeter
|| a
== 0 )
815 token
= text
.substr(tokenStart
,pos
-tokenStart
);
817 size_t len
= token
.length();
819 if ( !addOnlyIfNotEmpty
|| len
> 0 )
821 const wxPGProperty
* child
= Item(curChild
);
824 wxLogDebug(wxT("token = '%s', child = %s"),token
.c_str(),child
->GetLabel().c_str());
829 bool wasUnspecified
= child
->IsValueUnspecified();
831 wxVariant
variant(child
->GetValueRef());
832 if ( child
->StringToValue(variant
, token
, propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
834 variant
.SetName(child
->GetBaseName());
836 // Clear unspecified flag only if OnSetValue() didn't
838 if ( child
->IsValueUnspecified() &&
839 (wasUnspecified
|| !UsesAutoUnspecified()) )
841 variant
= child
->GetDefaultValue();
844 list
.Append(variant
);
851 // Empty, becomes unspecified
853 variant2
.SetName(child
->GetBaseName());
854 list
.Append(variant2
);
859 if ( curChild
>= iMax
)
863 tokenStart
= 0xFFFFFF;
868 // Token is not running
872 addOnlyIfNotEmpty
= false;
874 // Is this a group of tokens?
879 if ( it
!= text
.end() ) it
++;
881 size_t startPos
= pos
;
883 // Group item - find end
884 while ( it
!= text
.end() && depth
> 0 )
892 else if ( a
== wxS('[') )
896 token
= text
.substr(startPos
,pos
-startPos
-1);
898 if ( !token
.length() )
901 const wxPGProperty
* child
= Item(curChild
);
903 wxVariant oldChildValue
= child
->GetValue();
904 wxVariant
variant(oldChildValue
);
905 bool stvRes
= child
->StringToValue( variant
, token
, propagatedFlags
);
906 if ( stvRes
|| (variant
!= oldChildValue
) )
913 // Failed, becomes unspecified
918 variant
.SetName(child
->GetBaseName());
919 list
.Append(variant
);
922 if ( curChild
>= iMax
)
925 addOnlyIfNotEmpty
= true;
927 tokenStart
= 0xFFFFFF;
933 if ( a
== delimeter
)
946 if ( it
!= text
.end() )
963 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags
)
965 wxVariant
variant(m_value
);
966 bool res
= StringToValue(variant
, text
, argFlags
);
972 bool wxPGProperty::SetValueFromInt( long number
, int argFlags
)
974 wxVariant
variant(m_value
);
975 bool res
= IntToValue(variant
, number
, argFlags
);
981 wxSize
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const
984 return wxSize(m_valueBitmap
->GetWidth(),-1);
989 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const
991 return wxPGGlobalVars
->m_defaultRenderer
;
994 void wxPGProperty::OnCustomPaint( wxDC
& dc
,
998 wxBitmap
* bmp
= m_valueBitmap
;
1000 wxCHECK_RET( bmp
&& bmp
->Ok(), wxT("invalid bitmap") );
1002 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
1004 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
1007 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const
1009 return wxPGEditor_TextCtrl
;
1012 // Default extra property event handling - that is, none at all.
1013 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
1019 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
1021 // If auto unspecified values are not wanted (via window or property style),
1022 // then get default value instead of wxNullVariant.
1023 if ( value
.IsNull() && (flags
& wxPG_SETVAL_BY_USER
) &&
1024 !UsesAutoUnspecified() )
1026 value
= GetDefaultValue();
1029 if ( !value
.IsNull() )
1031 wxVariant tempListVariant
;
1034 // List variants are reserved a special purpose
1035 // as intermediate containers for child values
1036 // of properties with children.
1037 if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1040 // However, situation is different for composed string properties
1041 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
1043 tempListVariant
= value
;
1044 pList
= &tempListVariant
;
1048 AdaptListToValue(value
, &newValue
);
1050 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
1053 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
1054 flags
|= wxPG_SETVAL_AGGREGATED
;
1056 if ( pList
&& !pList
->IsNull() )
1058 wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST
);
1059 wxASSERT( GetChildCount() );
1060 wxASSERT( !IsCategory() );
1062 wxVariantList
& list
= pList
->GetList();
1063 wxVariantList::iterator node
;
1066 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
1068 // Children in list can be in any order, but we will give hint to
1069 // GetPropertyByNameWH(). This optimizes for full list parsing.
1070 for ( node
= list
.begin(); node
!= list
.end(); node
++ )
1072 wxVariant
& childValue
= *((wxVariant
*)*node
);
1073 wxPGProperty
* child
= GetPropertyByNameWH(childValue
.GetName(), i
);
1076 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
1077 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1079 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
1081 wxVariant listRefCopy
= childValue
;
1082 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
1086 wxVariant oldVal
= child
->GetValue();
1087 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
1090 else if ( child
->GetValue() != childValue
)
1092 // For aggregate properties, we will trust RefreshChildren()
1093 // to update child values.
1094 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
1095 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1096 if ( flags
& wxPG_SETVAL_BY_USER
)
1097 child
->SetFlag(wxPG_PROP_MODIFIED
);
1104 if ( !value
.IsNull() )
1109 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
1110 UpdateParentValues();
1113 if ( flags
& wxPG_SETVAL_BY_USER
)
1114 SetFlag(wxPG_PROP_MODIFIED
);
1116 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1121 if ( m_commonValue
!= -1 )
1123 wxPropertyGrid
* pg
= GetGrid();
1124 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
1130 // Set children to unspecified, but only if aggregate or
1131 // value is <composed>
1132 if ( AreChildrenComponents() )
1135 for ( i
=0; i
<GetChildCount(); i
++ )
1136 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1141 // Update editor control
1144 // We need to check for these, otherwise GetGrid() may fail.
1145 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1150 void wxPGProperty::SetValueInEvent( wxVariant value
) const
1152 GetGrid()->ValueChangeInEvent(value
);
1155 void wxPGProperty::SetFlagRecursively( FlagType flag
, bool set
)
1163 for ( i
= 0; i
< GetChildCount(); i
++ )
1164 Item(i
)->SetFlagRecursively(flag
, set
);
1167 void wxPGProperty::RefreshEditor()
1169 if ( m_parent
&& GetParentState() )
1171 wxPropertyGrid
* pg
= GetParentState()->GetGrid();
1172 if ( pg
->GetSelectedProperty() == this )
1174 wxWindow
* editor
= pg
->GetEditorControl();
1176 GetEditorClass()->UpdateControl( this, editor
);
1182 wxVariant
wxPGProperty::GetDefaultValue() const
1184 wxVariant defVal
= GetAttribute(wxS("DefaultValue"));
1185 if ( !defVal
.IsNull() )
1188 wxVariant value
= GetValue();
1190 if ( !value
.IsNull() )
1192 wxString
valueType(value
.GetType());
1194 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1195 return wxPGVariant_Zero
;
1196 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1197 return wxPGVariant_EmptyString
;
1198 if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1199 return wxPGVariant_False
;
1200 if ( valueType
== wxPG_VARIANT_TYPE_DOUBLE
)
1201 return wxVariant(0.0);
1202 if ( valueType
== wxPG_VARIANT_TYPE_ARRSTRING
)
1203 return wxVariant(wxArrayString());
1204 if ( valueType
== wxS("wxLongLong") )
1205 return WXVARIANT(wxLongLong(0));
1206 if ( valueType
== wxS("wxULongLong") )
1207 return WXVARIANT(wxULongLong(0));
1208 if ( valueType
== wxS("wxColour") )
1209 return WXVARIANT(*wxBLACK
);
1211 if ( valueType
== wxPG_VARIANT_TYPE_DATETIME
)
1212 return wxVariant(wxDateTime::Now());
1214 if ( valueType
== wxS("wxFont") )
1215 return WXVARIANT(*wxNORMAL_FONT
);
1216 if ( valueType
== wxS("wxPoint") )
1217 return WXVARIANT(wxPoint(0, 0));
1218 if ( valueType
== wxS("wxSize") )
1219 return WXVARIANT(wxSize(0, 0));
1225 void wxPGProperty::SetCell( int column
, wxPGCell
* cellObj
)
1227 if ( column
>= (int)m_cells
.size() )
1228 m_cells
.SetCount(column
+1, NULL
);
1230 delete (wxPGCell
*) m_cells
[column
];
1231 m_cells
[column
] = cellObj
;
1234 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const
1239 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1244 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value
)
1246 if ( DoSetAttribute( name
, value
) )
1248 // Support working without grid, when possible
1249 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1253 m_attributes
.Set( name
, value
);
1256 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes
)
1258 wxPGAttributeStorage::const_iterator it
= attributes
.StartIteration();
1261 while ( attributes
.GetNext(it
, variant
) )
1262 SetAttribute( variant
.GetName(), variant
);
1265 wxVariant
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1271 wxVariant
wxPGProperty::GetAttribute( const wxString
& name
) const
1273 return m_attributes
.FindValue(name
);
1276 wxString
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1278 wxVariant variant
= m_attributes
.FindValue(name
);
1280 if ( !variant
.IsNull() )
1281 return variant
.GetString();
1286 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1288 wxVariant variant
= m_attributes
.FindValue(name
);
1290 return wxPGVariantToInt(variant
, defVal
);
1293 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1296 wxVariant variant
= m_attributes
.FindValue(name
);
1298 if ( wxPGVariantToDouble(variant
, &retVal
) )
1304 wxVariant
wxPGProperty::GetAttributesAsList() const
1306 wxVariantList tempList
;
1307 wxVariant
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) );
1309 wxPGAttributeStorage::const_iterator it
= m_attributes
.StartIteration();
1312 while ( m_attributes
.GetNext(it
, variant
) )
1318 // Slots of utility flags are NULL
1319 const unsigned int gs_propFlagToStringSize
= 14;
1321 static const wxChar
* gs_propFlagToString
[gs_propFlagToStringSize
] = {
1338 wxString
wxPGProperty::GetFlagsAsString( FlagType flagsMask
) const
1341 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1345 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1347 if ( relevantFlags
& a
)
1349 const wxChar
* fs
= gs_propFlagToString
[i
];
1361 void wxPGProperty::SetFlagsFromString( const wxString
& str
)
1365 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1367 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1369 const wxChar
* fs
= gs_propFlagToString
[i
];
1370 if ( fs
&& str
== fs
)
1376 WX_PG_TOKENIZER1_END()
1378 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1381 wxValidator
* wxPGProperty::DoGetValidator() const
1383 return (wxValidator
*) NULL
;
1386 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value
)
1388 wxPropertyGrid
* pg
= GetGrid();
1389 int sel
= GetChoiceSelection();
1393 if ( index
== wxNOT_FOUND
)
1394 index
= m_choices
.GetCount();
1399 m_choices
.Insert(label
, index
, value
);
1401 if ( sel
!= newSel
)
1402 SetChoiceSelection(newSel
);
1404 if ( this == pg
->GetSelection() )
1405 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1411 void wxPGProperty::DeleteChoice( int index
)
1413 wxPropertyGrid
* pg
= GetGrid();
1415 int sel
= GetChoiceSelection();
1418 // Adjust current value
1421 SetValueToUnspecified();
1424 else if ( index
< sel
)
1429 m_choices
.RemoveAt(index
);
1431 if ( sel
!= newSel
)
1432 SetChoiceSelection(newSel
);
1434 if ( this == pg
->GetSelection() )
1435 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1438 int wxPGProperty::GetChoiceSelection() const
1440 wxVariant value
= GetValue();
1441 wxString valueType
= value
.GetType();
1442 int index
= wxNOT_FOUND
;
1444 if ( IsValueUnspecified() || !m_choices
.GetCount() )
1447 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1449 index
= value
.GetLong();
1451 else if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1453 index
= m_choices
.Index(value
.GetString());
1455 else if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1457 index
= value
.GetBool()? 1 : 0;
1463 void wxPGProperty::SetChoiceSelection( int newValue
)
1465 // Changes value of a property with choices, but only
1466 // works if the value type is long or string.
1467 wxString valueType
= GetValue().GetType();
1469 wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") );
1471 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1473 SetValue( m_choices
.GetLabel(newValue
) );
1475 else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
1477 SetValue( (long) newValue
);
1481 bool wxPGProperty::SetChoices( wxPGChoices
& choices
)
1483 m_choices
.Assign(choices
);
1486 // This may be needed to trigger some initialization
1487 // (but don't do it if property is somewhat uninitialized)
1488 wxVariant defVal
= GetDefaultValue();
1489 if ( defVal
.IsNull() )
1499 const wxPGEditor
* wxPGProperty::GetEditorClass() const
1501 const wxPGEditor
* editor
;
1503 if ( !m_customEditor
)
1505 editor
= DoGetEditorClass();
1508 editor
= m_customEditor
;
1511 // Maybe override editor if common value specified
1512 if ( GetDisplayedCommonValueCount() )
1514 // TextCtrlAndButton -> ComboBoxAndButton
1515 if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) )
1516 editor
= wxPGEditor_ChoiceAndButton
;
1518 // TextCtrl -> ComboBox
1519 else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) )
1520 editor
= wxPGEditor_ComboBox
;
1526 bool wxPGProperty::HasVisibleChildren() const
1530 for ( i
=0; i
<GetChildCount(); i
++ )
1532 wxPGProperty
* child
= Item(i
);
1534 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
1541 bool wxPGProperty::RecreateEditor()
1543 wxPropertyGrid
* pg
= GetGrid();
1546 wxPGProperty
* selected
= pg
->GetSelection();
1547 if ( this == selected
)
1549 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
1556 void wxPGProperty::SetValueImage( wxBitmap
& bmp
)
1558 delete m_valueBitmap
;
1560 if ( &bmp
&& bmp
.Ok() )
1563 wxSize maxSz
= GetGrid()->GetImageSize();
1564 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
1566 if ( imSz
.x
!= maxSz
.x
|| imSz
.y
!= maxSz
.y
)
1568 // Create a memory DC
1569 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
1572 dc
.SelectObject(*bmpNew
);
1575 // FIXME: This is ugly - use image or wait for scaling patch.
1576 double scaleX
= (double)maxSz
.x
/ (double)imSz
.x
;
1577 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
1579 dc
.SetUserScale(scaleX
,scaleY
);
1581 dc
.DrawBitmap( bmp
, 0, 0 );
1583 m_valueBitmap
= bmpNew
;
1587 m_valueBitmap
= new wxBitmap(bmp
);
1590 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1594 m_valueBitmap
= NULL
;
1595 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
1600 wxPGProperty
* wxPGProperty::GetMainParent() const
1602 const wxPGProperty
* curChild
= this;
1603 const wxPGProperty
* curParent
= m_parent
;
1605 while ( curParent
&& !curParent
->IsCategory() )
1607 curChild
= curParent
;
1608 curParent
= curParent
->m_parent
;
1611 return (wxPGProperty
*) curChild
;
1615 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const
1618 // Returns last visible sub-item, recursively.
1619 if ( !IsExpanded() || !GetChildCount() )
1622 return Last()->GetLastVisibleSubItem();
1626 bool wxPGProperty::IsVisible() const
1628 const wxPGProperty
* parent
;
1630 if ( HasFlag(wxPG_PROP_HIDDEN
) )
1633 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
1635 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
1642 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const
1644 wxPropertyGridPageState
* state
= GetParentState();
1645 wxPropertyGrid
* propGrid
= state
->GetGrid();
1646 if ( state
== propGrid
->GetState() )
1652 int wxPGProperty::GetY2( int lh
) const
1654 const wxPGProperty
* parent
;
1655 const wxPGProperty
* child
= this;
1659 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
1661 if ( !parent
->IsExpanded() )
1663 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
1668 y
-= lh
; // need to reduce one level
1674 int wxPGProperty::GetY() const
1676 return GetY2(GetGrid()->GetRowHeight());
1679 // This is used by Insert etc.
1680 void wxPGProperty::AddChild2( wxPGProperty
* prop
, int index
, bool correct_mode
)
1682 if ( index
< 0 || (size_t)index
>= m_children
.size() )
1684 if ( correct_mode
) prop
->m_arrIndex
= m_children
.size();
1685 m_children
.push_back( prop
);
1689 m_children
.insert( m_children
.begin()+index
, prop
);
1690 if ( correct_mode
) FixIndicesOfChildren( index
);
1693 prop
->m_parent
= this;
1696 // This is used by properties that have fixed sub-properties
1697 void wxPGProperty::AddChild( wxPGProperty
* prop
)
1699 wxASSERT_MSG( prop
->GetBaseName().length(),
1700 "Property's children must have unique, non-empty names within their scope" );
1702 prop
->m_arrIndex
= m_children
.size();
1703 m_children
.push_back( prop
);
1705 int custImgHeight
= prop
->OnMeasureImage().y
;
1706 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
1707 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1709 prop
->m_parent
= this;
1712 void wxPGProperty::RemoveChild( wxPGProperty
* p
)
1714 wxArrayPGProperty::iterator it
;
1715 wxArrayPGProperty
& children
= m_children
;
1717 for ( it
=children
.begin(); it
!= children
.end(); it
++ )
1721 m_children
.erase(it
);
1727 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
1729 wxASSERT( GetChildCount() );
1730 wxASSERT( !IsCategory() );
1732 *value
= GetValue();
1734 if ( !list
.GetCount() )
1737 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
1739 bool allChildrenSpecified
;
1741 // Don't fully update aggregate properties unless all children have
1743 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1744 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
1746 allChildrenSpecified
= true;
1748 wxVariant childValue
= list
[0];
1752 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
1754 for ( i
=0; i
<GetChildCount(); i
++ )
1756 const wxPGProperty
* child
= Item(i
);
1758 if ( childValue
.GetName() == child
->GetBaseName() )
1760 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
1762 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1764 wxVariant
cv2(child
->GetValue());
1765 child
->AdaptListToValue(childValue
, &cv2
);
1769 if ( allChildrenSpecified
)
1770 ChildChanged(*value
, i
, childValue
);
1772 if ( n
== (unsigned int)list
.GetCount() )
1774 childValue
= list
[n
];
1780 void wxPGProperty::FixIndicesOfChildren( unsigned int starthere
)
1783 for ( i
=starthere
;i
<GetChildCount();i
++)
1784 Item(i
)->m_arrIndex
= i
;
1788 // Returns (direct) child property with given name (or NULL if not found)
1789 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name
) const
1793 for ( i
=0; i
<GetChildCount(); i
++ )
1795 wxPGProperty
* p
= Item(i
);
1796 if ( p
->m_name
== name
)
1800 // Does it have point, then?
1801 int pos
= name
.Find(wxS('.'));
1803 return (wxPGProperty
*) NULL
;
1805 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
1807 if ( !p
|| !p
->GetChildCount() )
1810 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
1813 wxPGProperty
* wxPGProperty::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex
) const
1815 unsigned int i
= hintIndex
;
1817 if ( i
>= GetChildCount() )
1820 unsigned int lastIndex
= i
- 1;
1822 if ( lastIndex
>= GetChildCount() )
1823 lastIndex
= GetChildCount() - 1;
1827 wxPGProperty
* p
= Item(i
);
1828 if ( p
->m_name
== name
)
1831 if ( i
== lastIndex
)
1835 if ( i
== GetChildCount() )
1842 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_
) const
1844 // Returns height of children, recursively, and
1845 // by taking expanded/collapsed status into account.
1847 // iMax is used when finding property y-positions.
1853 iMax_
= GetChildCount();
1855 unsigned int iMax
= iMax_
;
1857 wxASSERT( iMax
<= GetChildCount() );
1859 if ( !IsExpanded() && GetParent() )
1864 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
1866 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1868 if ( !pwc
->IsExpanded() ||
1869 pwc
->GetChildCount() == 0 )
1872 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
1881 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
, unsigned int lh
, unsigned int* nextItemY
) const
1883 wxASSERT( nextItemY
);
1885 // Linear search at the moment
1887 // nextItemY = y of next visible property, final value will be written back.
1888 wxPGProperty
* result
= NULL
;
1889 wxPGProperty
* current
= NULL
;
1890 unsigned int iy
= *nextItemY
;
1892 unsigned int iMax
= GetChildCount();
1896 wxPGProperty
* pwc
= Item(i
);
1898 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1909 if ( pwc
->IsExpanded() &&
1910 pwc
->GetChildCount() > 0 )
1912 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
1924 if ( !result
&& y
< iy
)
1931 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
1933 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
1936 return (wxPGProperty
*) result
;
1939 void wxPGProperty::Empty()
1942 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
1944 for ( i
=0; i
<GetChildCount(); i
++ )
1946 delete m_children
[i
];
1953 void wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
1954 int WXUNUSED(childIndex
),
1955 wxVariant
& WXUNUSED(childValue
) ) const
1959 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList
) const
1963 const wxVariantList
* pList
= NULL
;
1964 wxVariantList::const_iterator node
;
1968 pList
= &pendingList
->GetList();
1969 node
= pList
->begin();
1972 for ( i
=0; i
<GetChildCount(); i
++ )
1974 wxPGProperty
* child
= Item(i
);
1975 const wxVariant
* listValue
= NULL
;
1980 const wxString
& childName
= child
->GetBaseName();
1982 for ( ; node
!= pList
->end(); node
++ )
1984 const wxVariant
& item
= *((const wxVariant
*)*node
);
1985 if ( item
.GetName() == childName
)
1995 value
= child
->GetValue();
1997 if ( value
.IsNull() )
2000 // Check recursively
2001 if ( child
->GetChildCount() )
2003 const wxVariant
* childList
= NULL
;
2005 if ( listValue
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST
)
2006 childList
= listValue
;
2008 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
2016 wxPGProperty
* wxPGProperty::UpdateParentValues()
2018 wxPGProperty
* parent
= m_parent
;
2019 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
2020 !parent
->IsCategory() && !parent
->IsRoot() )
2023 parent
->GenerateComposedValue(s
, 0);
2024 parent
->m_value
= s
;
2025 return parent
->UpdateParentValues();
2030 bool wxPGProperty::IsTextEditable() const
2032 if ( HasFlag(wxPG_PROP_READONLY
) )
2035 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
2037 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
2044 // Call after fixed sub-properties added/removed after creation.
2045 // if oldSelInd >= 0 and < new max items, then selection is
2046 // moved to it. Note: oldSelInd -2 indicates that this property
2047 // should be selected.
2048 void wxPGProperty::SubPropsChanged( int oldSelInd
)
2050 wxPropertyGridPageState
* state
= GetParentState();
2051 wxPropertyGrid
* grid
= state
->GetGrid();
2054 // Re-repare children (recursively)
2055 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
2057 wxPGProperty
* child
= Item(i
);
2058 child
->InitAfterAdded(state
, grid
);
2061 wxPGProperty
* sel
= (wxPGProperty
*) NULL
;
2062 if ( oldSelInd
>= (int)m_children
.size() )
2063 oldSelInd
= (int)m_children
.size() - 1;
2065 if ( oldSelInd
>= 0 )
2066 sel
= m_children
[oldSelInd
];
2067 else if ( oldSelInd
== -2 )
2071 state
->DoSelectProperty(sel
);
2073 if ( state
== grid
->GetState() )
2075 grid
->GetPanel()->Refresh();
2079 // -----------------------------------------------------------------------
2081 // -----------------------------------------------------------------------
2083 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2084 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2087 wxPGRootProperty::wxPGRootProperty()
2091 m_name
= wxS("<root>");
2098 wxPGRootProperty::~wxPGRootProperty()
2103 // -----------------------------------------------------------------------
2104 // wxPropertyCategory
2105 // -----------------------------------------------------------------------
2107 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2108 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2110 void wxPropertyCategory::Init()
2112 // don't set colour - prepareadditem method should do this
2113 SetParentalType(wxPG_PROP_CATEGORY
);
2114 m_capFgColIndex
= 1;
2118 wxPropertyCategory::wxPropertyCategory()
2125 wxPropertyCategory::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2126 : wxPGProperty(label
,name
)
2132 wxPropertyCategory::~wxPropertyCategory()
2137 wxString
wxPropertyCategory::GetValueAsString( int ) const
2139 return wxEmptyString
;
2142 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2144 if ( m_textExtent
> 0 )
2145 return m_textExtent
;
2147 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2151 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2154 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2158 // -----------------------------------------------------------------------
2159 // wxPGAttributeStorage
2160 // -----------------------------------------------------------------------
2162 wxPGAttributeStorage::wxPGAttributeStorage()
2166 wxPGAttributeStorage::~wxPGAttributeStorage()
2168 wxPGHashMapS2P::iterator it
;
2170 for ( it
= m_map
.begin(); it
!= m_map
.end(); it
++ )
2172 wxVariantData
* data
= (wxVariantData
*) it
->second
;
2177 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value
)
2179 wxVariantData
* data
= value
.GetData();
2182 wxPGHashMapS2P::iterator it
= m_map
.find(name
);
2183 if ( it
!= m_map
.end() )
2185 ((wxVariantData
*)it
->second
)->DecRef();
2189 // If Null variant, just remove from set
2203 #endif // wxUSE_PROPGRID