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 licence
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 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
99 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
102 void wxPGCellRenderer::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
103 int xOffset
, const wxString
& text
,
104 wxPGProperty
* property
,
105 const wxPGEditor
* editor
) const
107 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
114 rect2
.height
-= yOffset
;
115 editor
->DrawValue( dc
, rect2
, property
, text
);
120 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
125 void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
127 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
128 wxPGDrawFocusRect(dc
,focusRect
);
131 int wxPGCellRenderer::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
135 // If possible, use cell colours
136 if ( !(flags
& DontUseCellBgCol
) )
138 const wxColour
& bgCol
= cell
.GetBgCol();
143 if ( !(flags
& DontUseCellFgCol
) )
145 dc
.SetTextForeground(cell
.GetFgCol());
148 // Draw Background, but only if not rendering in control
149 // (as control already has rendered correct background).
150 if ( !(flags
& (Control
|ChoicePopup
)) )
151 dc
.DrawRectangle(rect
);
153 // Use cell font, if provided
154 const wxFont
& font
= cell
.GetFont();
158 const wxBitmap
& bmp
= cell
.GetBitmap();
160 // Do not draw oversized bitmap outside choice popup
161 ((flags
& ChoicePopup
) || bmp
.GetHeight() < rect
.height
)
165 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
166 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
168 imageWidth
= bmp
.GetWidth();
174 void wxPGCellRenderer::PostDrawCell( wxDC
& dc
,
175 const wxPropertyGrid
* propGrid
,
176 const wxPGCell
& cell
,
177 int WXUNUSED(flags
) ) const
180 const wxFont
& font
= cell
.GetFont();
182 dc
.SetFont(propGrid
->GetFont());
185 // -----------------------------------------------------------------------
186 // wxPGDefaultRenderer
187 // -----------------------------------------------------------------------
189 bool wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
,
190 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
191 int column
, int item
, int flags
) const
193 const wxPGEditor
* editor
= NULL
;
194 const wxPGCell
* cell
= NULL
;
197 bool isUnspecified
= property
->IsValueUnspecified();
199 if ( column
== 1 && item
== -1 )
201 int cmnVal
= property
->GetCommonValue();
205 if ( !isUnspecified
)
207 text
= propertyGrid
->GetCommonValueLabel(cmnVal
);
208 DrawText( dc
, rect
, 0, text
);
217 int preDrawFlags
= flags
;
220 property
->GetDisplayInfo(column
, item
, flags
, &text
, &cell
);
222 imageWidth
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
226 editor
= property
->GetColumnEditor(column
);
228 if ( !isUnspecified
)
230 // Regular property value
232 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
234 wxPGPaintData paintdata
;
235 paintdata
.m_parent
= propertyGrid
;
236 paintdata
.m_choiceItem
= item
;
238 if ( imageSize
.x
> 0 )
240 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
241 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
242 wxPG_CUSTOM_IMAGE_WIDTH
,
243 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
245 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
247 paintdata
.m_drawnWidth
= imageSize
.x
;
248 paintdata
.m_drawnHeight
= imageSize
.y
;
250 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
252 imageWidth
= paintdata
.m_drawnWidth
;
255 text
= property
->GetValueAsString();
258 if ( propertyGrid
->GetColumnCount() <= 2 )
260 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
261 if ( unitsString
.length() )
262 text
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
266 if ( text
.length() == 0 )
268 text
= property
->GetHintText();
269 if ( text
.length() > 0 )
273 const wxColour
& hCol
=
274 propertyGrid
->GetCellDisabledTextColour();
275 dc
.SetTextForeground(hCol
);
277 // Must make the editor NULL to override it's own rendering
288 int imageOffset
= property
->GetImageOffset(imageWidth
);
290 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
292 // active caption gets nice dotted rectangle
293 if ( property
->IsCategory() && column
== 0 )
295 if ( flags
& Selected
)
297 if ( imageOffset
> 0 )
299 imageOffset
-= DEFAULT_IMAGE_OFFSET_INCREMENT
;
300 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
303 DrawCaptionSelectionRect( dc
,
304 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
305 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
306 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
307 propertyGrid
->GetCaptionFont())
308 +(wxPG_CAPRECTXMARGIN
*2),
309 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
313 PostDrawCell(dc
, propertyGrid
, *cell
, preDrawFlags
);
318 wxSize
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
,
322 if ( property
&& column
== 1 )
326 wxBitmap
* bmp
= property
->GetValueImage();
328 if ( bmp
&& bmp
->Ok() )
329 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
335 // -----------------------------------------------------------------------
337 // -----------------------------------------------------------------------
339 wxPGCellData::wxPGCellData()
342 m_hasValidText
= false;
345 // -----------------------------------------------------------------------
347 // -----------------------------------------------------------------------
354 wxPGCell::wxPGCell( const wxString
& text
,
355 const wxBitmap
& bitmap
,
356 const wxColour
& fgCol
,
357 const wxColour
& bgCol
)
360 wxPGCellData
* data
= new wxPGCellData();
363 data
->m_bitmap
= bitmap
;
364 data
->m_fgCol
= fgCol
;
365 data
->m_bgCol
= bgCol
;
366 data
->m_hasValidText
= true;
369 wxObjectRefData
*wxPGCell::CloneRefData( const wxObjectRefData
*data
) const
371 wxPGCellData
* c
= new wxPGCellData();
372 const wxPGCellData
* o
= (const wxPGCellData
*) data
;
373 c
->m_text
= o
->m_text
;
374 c
->m_bitmap
= o
->m_bitmap
;
375 c
->m_fgCol
= o
->m_fgCol
;
376 c
->m_bgCol
= o
->m_bgCol
;
377 c
->m_hasValidText
= o
->m_hasValidText
;
381 void wxPGCell::SetText( const wxString
& text
)
385 GetData()->SetText(text
);
388 void wxPGCell::SetBitmap( const wxBitmap
& bitmap
)
392 GetData()->SetBitmap(bitmap
);
395 void wxPGCell::SetFgCol( const wxColour
& col
)
399 GetData()->SetFgCol(col
);
402 void wxPGCell::SetFont( const wxFont
& font
)
406 GetData()->SetFont(font
);
409 void wxPGCell::SetBgCol( const wxColour
& col
)
413 GetData()->SetBgCol(col
);
416 void wxPGCell::MergeFrom( const wxPGCell
& srcCell
)
420 wxPGCellData
* data
= GetData();
422 if ( srcCell
.HasText() )
423 data
->SetText(srcCell
.GetText());
425 if ( srcCell
.GetFgCol().IsOk() )
426 data
->SetFgCol(srcCell
.GetFgCol());
428 if ( srcCell
.GetBgCol().IsOk() )
429 data
->SetBgCol(srcCell
.GetBgCol());
431 if ( srcCell
.GetBitmap().IsOk() )
432 data
->SetBitmap(srcCell
.GetBitmap());
435 void wxPGCell::SetEmptyData()
441 // -----------------------------------------------------------------------
443 // -----------------------------------------------------------------------
445 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
447 wxString
* wxPGProperty::sm_wxPG_LABEL
= NULL
;
449 void wxPGProperty::Init()
455 m_parentState
= NULL
;
458 m_clientObject
= NULL
;
460 m_customEditor
= NULL
;
464 m_valueBitmap
= NULL
;
466 m_maxLen
= 0; // infinite maximum length
468 m_flags
= wxPG_PROP_PROPERTY
;
476 void wxPGProperty::Init( const wxString
& label
, const wxString
& name
)
478 // We really need to check if &label and &name are NULL pointers
479 // (this can if we are called before property grid has been initalized)
481 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
484 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
487 DoSetName( m_label
);
492 void wxPGProperty::InitAfterAdded( wxPropertyGridPageState
* pageState
,
493 wxPropertyGrid
* propgrid
)
496 // Called after property has been added to grid or page
497 // (so propgrid can be NULL, too).
499 wxPGProperty
* parent
= m_parent
;
500 bool parentIsRoot
= parent
->IsKindOf(CLASSINFO(wxPGRootProperty
));
502 m_parentState
= pageState
;
504 #if wxPG_COMPATIBILITY_1_4
505 // Make sure deprecated virtual functions are not implemented
506 wxString s
= GetValueAsString( 0xFFFF );
507 wxASSERT_MSG( s
== g_invalidStringContent
,
508 "Implement ValueToString() instead of GetValueAsString()" );
511 if ( !parentIsRoot
&& !parent
->IsCategory() )
513 m_cells
= parent
->m_cells
;
516 // If in hideable adding mode, or if assigned parent is hideable, then
517 // make this one hideable.
519 ( !parentIsRoot
&& parent
->HasFlag(wxPG_PROP_HIDDEN
) ) ||
520 ( propgrid
&& (propgrid
->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES
)) )
522 SetFlag( wxPG_PROP_HIDDEN
);
524 // Set custom image flag.
525 int custImgHeight
= OnMeasureImage().y
;
526 if ( custImgHeight
< 0 )
528 SetFlag(wxPG_PROP_CUSTOMIMAGE
);
531 if ( propgrid
&& (propgrid
->HasFlag(wxPG_LIMITED_EDITING
)) )
532 SetFlag(wxPG_PROP_NOEDITOR
);
534 // Make sure parent has some parental flags
535 if ( !parent
->HasFlag(wxPG_PROP_PARENTAL_FLAGS
) )
536 parent
->SetParentalType(wxPG_PROP_MISC_PARENT
);
540 // This is not a category.
544 unsigned char depth
= 1;
547 depth
= parent
->m_depth
;
548 if ( !parent
->IsCategory() )
552 unsigned char greyDepth
= depth
;
556 wxPropertyCategory
* pc
;
558 if ( parent
->IsCategory() )
559 pc
= (wxPropertyCategory
* ) parent
;
561 // This conditional compile is necessary to
562 // bypass some compiler bug.
563 pc
= pageState
->GetPropertyCategory(parent
);
566 greyDepth
= pc
->GetDepth();
568 greyDepth
= parent
->m_depthBgCol
;
571 m_depthBgCol
= greyDepth
;
575 // This is a category.
578 unsigned char depth
= 1;
581 depth
= parent
->m_depth
+ 1;
584 m_depthBgCol
= depth
;
588 // Has initial children
589 if ( GetChildCount() )
591 // Check parental flags
592 wxASSERT_MSG( ((m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
593 wxPG_PROP_AGGREGATE
) ||
594 ((m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
595 wxPG_PROP_MISC_PARENT
),
596 "wxPGProperty parental flags set incorrectly at "
599 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
601 // Properties with private children are not expanded by default.
604 else if ( propgrid
&& propgrid
->HasFlag(wxPG_HIDE_MARGIN
) )
606 // ...unless it cannot be expanded by user and therefore must
607 // remain visible at all times
612 // Prepare children recursively
613 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
615 wxPGProperty
* child
= Item(i
);
616 child
->InitAfterAdded(pageState
, pageState
->GetGrid());
619 if ( propgrid
&& (propgrid
->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES
) )
620 SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED
, true);
624 wxPGProperty::wxPGProperty()
631 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name
)
638 wxPGProperty::~wxPGProperty()
640 delete m_clientObject
;
642 Empty(); // this deletes items
644 delete m_valueBitmap
;
649 // This makes it easier for us to detect dangling pointers
654 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate
) const
656 wxPGProperty
* parent
= m_parent
;
659 if ( parent
== candidate
)
661 parent
= parent
->m_parent
;
666 void wxPGProperty::SetName( const wxString
& newName
)
668 wxPropertyGrid
* pg
= GetGrid();
671 pg
->SetPropertyName(this, newName
);
676 wxString
wxPGProperty::GetName() const
678 wxPGProperty
* parent
= GetParent();
680 if ( !m_name
.length() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
683 return m_parent
->GetName() + wxS(".") + m_name
;
686 wxPropertyGrid
* wxPGProperty::GetGrid() const
688 if ( !m_parentState
)
690 return m_parentState
->GetGrid();
693 int wxPGProperty::Index( const wxPGProperty
* p
) const
695 return wxPGFindInVector(m_children
, p
);
698 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
703 void wxPGProperty::OnSetValue()
707 void wxPGProperty::RefreshChildren ()
711 void wxPGProperty::OnValidationFailure( wxVariant
& WXUNUSED(pendingValue
) )
715 void wxPGProperty::GetDisplayInfo( unsigned int column
,
719 const wxPGCell
** pCell
)
721 const wxPGCell
* cell
= NULL
;
723 if ( !(flags
& wxPGCellRenderer::ChoicePopup
) )
725 // Not painting list of choice popups, so get text from property
726 if ( column
!= 1 || !IsValueUnspecified() || IsCategory() )
728 cell
= &GetCell(column
);
732 // Use special unspecified value cell
733 cell
= &GetGrid()->GetUnspecifiedValueAppearance();
736 if ( cell
->HasText() )
738 *pString
= cell
->GetText();
743 *pString
= GetLabel();
744 else if ( column
== 1 )
745 *pString
= GetDisplayedString();
746 else if ( column
== 2 )
747 *pString
= GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
752 wxASSERT( column
== 1 );
754 if ( choiceIndex
!= wxNOT_FOUND
)
756 const wxPGChoiceEntry
& entry
= m_choices
[choiceIndex
];
757 if ( entry
.GetBitmap().IsOk() ||
758 entry
.GetFgCol().IsOk() ||
759 entry
.GetBgCol().IsOk() )
761 *pString
= m_choices
.GetLabel(choiceIndex
);
766 cell
= &GetCell(column
);
768 wxASSERT_MSG( cell
->GetData(),
769 wxString::Format("Invalid cell for property %s",
770 GetName().c_str()) );
776 wxString wxPGProperty::GetColumnText( unsigned int col, int choiceIndex ) const
779 if ( col != 1 || choiceIndex == wxNOT_FOUND )
781 const wxPGCell& cell = GetCell(col);
782 if ( cell->HasText() )
784 return cell->GetText();
791 return GetDisplayedString();
793 return GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString);
799 return m_choices.GetLabel(choiceIndex);
802 return wxEmptyString;
806 void wxPGProperty::DoGenerateComposedValue( wxString
& text
,
808 const wxVariantList
* valueOverrides
,
809 wxPGHashMapS2S
* childResults
) const
812 int iMax
= m_children
.size();
818 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
819 !(argFlags
& wxPG_FULL_VALUE
) )
820 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
822 int iMaxMinusOne
= iMax
-1;
824 if ( !IsTextEditable() )
825 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
827 wxPGProperty
* curChild
= m_children
[0];
829 bool overridesLeft
= false;
830 wxVariant overrideValue
;
831 wxVariantList::const_iterator node
;
833 if ( valueOverrides
)
835 node
= valueOverrides
->begin();
836 if ( node
!= valueOverrides
->end() )
838 overrideValue
= *node
;
839 overridesLeft
= true;
843 for ( i
= 0; i
< iMax
; i
++ )
845 wxVariant childValue
;
847 wxString childLabel
= curChild
->GetLabel();
849 // Check for value override
850 if ( overridesLeft
&& overrideValue
.GetName() == childLabel
)
852 if ( !overrideValue
.IsNull() )
853 childValue
= overrideValue
;
855 childValue
= curChild
->GetValue();
857 if ( node
!= valueOverrides
->end() )
858 overrideValue
= *node
;
860 overridesLeft
= false;
864 childValue
= curChild
->GetValue();
868 if ( !childValue
.IsNull() )
870 if ( overridesLeft
&&
871 curChild
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
872 childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
874 wxVariantList
& childList
= childValue
.GetList();
875 DoGenerateComposedValue(s
, argFlags
|wxPG_COMPOSITE_FRAGMENT
,
876 &childList
, childResults
);
880 s
= curChild
->ValueToString(childValue
,
881 argFlags
|wxPG_COMPOSITE_FRAGMENT
);
885 if ( childResults
&& curChild
->GetChildCount() )
886 (*childResults
)[curChild
->GetName()] = s
;
889 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() )
892 if ( !curChild
->GetChildCount() || skip
)
895 text
+= wxS("[") + s
+ wxS("]");
897 if ( i
< iMaxMinusOne
)
899 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
900 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
901 !(argFlags
& wxPG_FULL_VALUE
) )
906 if ( !curChild
->GetChildCount() )
912 curChild
= m_children
[i
+1];
916 if ( (unsigned int)i
< m_children
.size() )
918 if ( !text
.EndsWith(wxS("; ")) )
919 text
+= wxS("; ...");
925 wxString
wxPGProperty::ValueToString( wxVariant
& WXUNUSED(value
),
928 wxCHECK_MSG( GetChildCount() > 0,
930 "If user property does not have any children, it must "
931 "override GetValueAsString" );
933 // FIXME: Currently code below only works if value is actually m_value
934 wxASSERT_MSG( argFlags
& wxPG_VALUE_IS_CURRENT
,
935 "Sorry, currently default wxPGProperty::ValueToString() "
936 "implementation only works if value is m_value." );
939 DoGenerateComposedValue(text
, argFlags
);
943 wxString
wxPGProperty::GetValueAsString( int argFlags
) const
945 #if wxPG_COMPATIBILITY_1_4
946 // This is backwards compatibility test
947 // That is, to make sure this function is not overridden
948 // (instead, ValueToString() should be).
949 if ( argFlags
== 0xFFFF )
951 // Do not override! (for backwards compliancy)
952 return g_invalidStringContent
;
956 wxPropertyGrid
* pg
= GetGrid();
958 if ( IsValueUnspecified() )
959 return pg
->GetUnspecifiedValueText(argFlags
);
961 if ( m_commonValue
== -1 )
963 wxVariant
value(GetValue());
964 return ValueToString(value
, argFlags
|wxPG_VALUE_IS_CURRENT
);
968 // Return common value's string representation
969 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
971 if ( argFlags
& wxPG_FULL_VALUE
)
973 return cv
->GetLabel();
975 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
977 return cv
->GetEditableText();
981 return cv
->GetLabel();
985 wxString
wxPGProperty::GetValueString( int argFlags
) const
987 return GetValueAsString(argFlags
);
990 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
992 variant
= (long)number
;
996 // Convert semicolon delimited tokens into child values.
997 bool wxPGProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
999 if ( !GetChildCount() )
1002 unsigned int curChild
= 0;
1004 unsigned int iMax
= m_children
.size();
1006 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
1007 !(argFlags
& wxPG_FULL_VALUE
) )
1008 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
1010 bool changed
= false;
1015 // Its best only to add non-empty group items
1016 bool addOnlyIfNotEmpty
= false;
1017 const wxChar delimeter
= wxS(';');
1019 size_t tokenStart
= 0xFFFFFF;
1021 wxVariantList temp_list
;
1022 wxVariant
list(temp_list
);
1024 int propagatedFlags
= argFlags
& (wxPG_REPORT_ERROR
|wxPG_PROGRAMMATIC_VALUE
);
1026 wxLogTrace("propgrid",
1027 wxT(">> %s.StringToValue('%s')"), GetLabel(), text
);
1029 wxString::const_iterator it
= text
.begin();
1032 if ( it
!= text
.end() )
1039 // How many units we iterate string forward at the end of loop?
1040 // We need to keep track of this or risk going to negative
1041 // with it-- operation.
1042 unsigned int strPosIncrement
= 1;
1044 if ( tokenStart
!= 0xFFFFFF )
1047 if ( a
== delimeter
|| a
== 0 )
1049 token
= text
.substr(tokenStart
,pos
-tokenStart
);
1051 size_t len
= token
.length();
1053 if ( !addOnlyIfNotEmpty
|| len
> 0 )
1055 const wxPGProperty
* child
= Item(curChild
);
1056 wxVariant
variant(child
->GetValue());
1057 wxString childName
= child
->GetBaseName();
1059 wxLogTrace("propgrid",
1060 wxT("token = '%s', child = %s"),
1063 // Add only if editable or setting programmatically
1064 if ( (argFlags
& wxPG_PROGRAMMATIC_VALUE
) ||
1065 (!child
->HasFlag(wxPG_PROP_DISABLED
) &&
1066 !child
->HasFlag(wxPG_PROP_READONLY
)) )
1070 if ( child
->StringToValue(variant
, token
,
1071 propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
1073 // We really need to set the variant's name
1074 // *after* child->StringToValue() has been
1075 // called, since variant's value may be set by
1076 // assigning another variant into it, which
1077 // then usually causes name to be copied (ie.
1078 // usually cleared) as well. wxBoolProperty
1079 // being case in point with its use of
1080 // wxPGVariant_Bool macro as an optimization.
1081 variant
.SetName(childName
);
1082 list
.Append(variant
);
1089 // Empty, becomes unspecified
1091 variant
.SetName(childName
);
1092 list
.Append(variant
);
1098 if ( curChild
>= iMax
)
1102 tokenStart
= 0xFFFFFF;
1107 // Token is not running
1108 if ( a
!= wxS(' ') )
1111 addOnlyIfNotEmpty
= false;
1113 // Is this a group of tokens?
1114 if ( a
== wxS('[') )
1118 if ( it
!= text
.end() ) ++it
;
1120 size_t startPos
= pos
;
1122 // Group item - find end
1123 while ( it
!= text
.end() && depth
> 0 )
1129 if ( a
== wxS(']') )
1131 else if ( a
== wxS('[') )
1135 token
= text
.substr(startPos
,pos
-startPos
-1);
1137 if ( !token
.length() )
1140 const wxPGProperty
* child
= Item(curChild
);
1142 wxVariant oldChildValue
= child
->GetValue();
1143 wxVariant
variant(oldChildValue
);
1145 if ( (argFlags
& wxPG_PROGRAMMATIC_VALUE
) ||
1146 (!child
->HasFlag(wxPG_PROP_DISABLED
) &&
1147 !child
->HasFlag(wxPG_PROP_READONLY
)) )
1149 wxString childName
= child
->GetBaseName();
1151 bool stvRes
= child
->StringToValue( variant
, token
,
1153 if ( stvRes
|| (variant
!= oldChildValue
) )
1155 variant
.SetName(childName
);
1156 list
.Append(variant
);
1167 if ( curChild
>= iMax
)
1170 addOnlyIfNotEmpty
= true;
1172 tokenStart
= 0xFFFFFF;
1178 if ( a
== delimeter
)
1179 strPosIncrement
-= 1;
1187 it
+= strPosIncrement
;
1189 if ( it
!= text
.end() )
1198 pos
+= strPosIncrement
;
1207 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags
)
1209 wxVariant
variant(m_value
);
1210 bool res
= StringToValue(variant
, text
, argFlags
);
1216 bool wxPGProperty::SetValueFromInt( long number
, int argFlags
)
1218 wxVariant
variant(m_value
);
1219 bool res
= IntToValue(variant
, number
, argFlags
);
1225 wxSize
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const
1227 if ( m_valueBitmap
)
1228 return wxSize(m_valueBitmap
->GetWidth(),-1);
1233 int wxPGProperty::GetImageOffset( int imageWidth
) const
1235 int imageOffset
= 0;
1239 // Do not increment offset too much for wide images
1240 if ( imageWidth
<= (wxPG_CUSTOM_IMAGE_WIDTH
+5) )
1241 imageOffset
= imageWidth
+ DEFAULT_IMAGE_OFFSET_INCREMENT
;
1243 imageOffset
= imageWidth
+ 1;
1249 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const
1251 return wxPGGlobalVars
->m_defaultRenderer
;
1254 void wxPGProperty::OnCustomPaint( wxDC
& dc
,
1258 wxBitmap
* bmp
= m_valueBitmap
;
1260 wxCHECK_RET( bmp
&& bmp
->Ok(), wxT("invalid bitmap") );
1262 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
1264 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
1267 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const
1269 return wxPGEditor_TextCtrl
;
1272 // Default extra property event handling - that is, none at all.
1273 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
1279 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
1281 // If auto unspecified values are not wanted (via window or property style),
1282 // then get default value instead of wxNullVariant.
1283 if ( value
.IsNull() && (flags
& wxPG_SETVAL_BY_USER
) &&
1284 !UsesAutoUnspecified() )
1286 value
= GetDefaultValue();
1289 if ( !value
.IsNull() )
1291 wxVariant tempListVariant
;
1294 // List variants are reserved a special purpose
1295 // as intermediate containers for child values
1296 // of properties with children.
1297 if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1300 // However, situation is different for composed string properties
1301 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
1303 tempListVariant
= value
;
1304 pList
= &tempListVariant
;
1308 AdaptListToValue(value
, &newValue
);
1310 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
1313 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
1314 flags
|= wxPG_SETVAL_AGGREGATED
;
1316 if ( pList
&& !pList
->IsNull() )
1318 wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST
);
1319 wxASSERT( GetChildCount() );
1320 wxASSERT( !IsCategory() );
1322 wxVariantList
& list
= pList
->GetList();
1323 wxVariantList::iterator node
;
1326 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
1328 // Children in list can be in any order, but we will give hint to
1329 // GetPropertyByNameWH(). This optimizes for full list parsing.
1330 for ( node
= list
.begin(); node
!= list
.end(); ++node
)
1332 wxVariant
& childValue
= *((wxVariant
*)*node
);
1333 wxPGProperty
* child
= GetPropertyByNameWH(childValue
.GetName(), i
);
1336 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
1337 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1339 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
1341 wxVariant listRefCopy
= childValue
;
1342 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
1346 wxVariant oldVal
= child
->GetValue();
1347 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
1350 else if ( child
->GetValue() != childValue
)
1352 // For aggregate properties, we will trust RefreshChildren()
1353 // to update child values.
1354 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
1355 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1356 if ( flags
& wxPG_SETVAL_BY_USER
)
1357 child
->SetFlag(wxPG_PROP_MODIFIED
);
1363 // Always call OnSetValue() for a parent property (do not call it
1364 // here if the value is non-null because it will then be called
1366 if ( value
.IsNull() )
1370 if ( !value
.IsNull() )
1376 if ( flags
& wxPG_SETVAL_BY_USER
)
1377 SetFlag(wxPG_PROP_MODIFIED
);
1379 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1384 if ( m_commonValue
!= -1 )
1386 wxPropertyGrid
* pg
= GetGrid();
1387 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
1393 // Set children to unspecified, but only if aggregate or
1394 // value is <composed>
1395 if ( AreChildrenComponents() )
1398 for ( i
=0; i
<GetChildCount(); i
++ )
1399 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1403 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
1404 UpdateParentValues();
1407 // Update editor control.
1408 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1410 wxPropertyGrid
* pg
= GetGridIfDisplayed();
1413 wxPGProperty
* selected
= pg
->GetSelectedProperty();
1415 // Only refresh the control if this was selected, or
1416 // this was some parent of selected, or vice versa)
1417 if ( selected
&& (selected
== this ||
1418 selected
->IsSomeParent(this) ||
1419 this->IsSomeParent(selected
)) )
1422 pg
->DrawItemAndValueRelated(this);
1428 void wxPGProperty::SetValueInEvent( wxVariant value
) const
1430 GetGrid()->ValueChangeInEvent(value
);
1433 void wxPGProperty::SetFlagRecursively( wxPGPropertyFlags flag
, bool set
)
1435 ChangeFlag(flag
, set
);
1438 for ( i
= 0; i
< GetChildCount(); i
++ )
1439 Item(i
)->SetFlagRecursively(flag
, set
);
1442 void wxPGProperty::RefreshEditor()
1447 wxPropertyGrid
* pg
= GetGrid();
1448 if ( pg
&& pg
->GetSelectedProperty() == this )
1449 pg
->RefreshEditor();
1452 wxVariant
wxPGProperty::GetDefaultValue() const
1454 wxVariant defVal
= GetAttribute(wxPG_ATTR_DEFAULT_VALUE
);
1455 if ( !defVal
.IsNull() )
1458 wxVariant value
= GetValue();
1460 if ( !value
.IsNull() )
1462 wxString
valueType(value
.GetType());
1464 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1465 return wxPGVariant_Zero
;
1466 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1467 return wxPGVariant_EmptyString
;
1468 if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1469 return wxPGVariant_False
;
1470 if ( valueType
== wxPG_VARIANT_TYPE_DOUBLE
)
1471 return wxVariant(0.0);
1472 if ( valueType
== wxPG_VARIANT_TYPE_ARRSTRING
)
1473 return wxVariant(wxArrayString());
1474 if ( valueType
== wxS("wxLongLong") )
1475 return WXVARIANT(wxLongLong(0));
1476 if ( valueType
== wxS("wxULongLong") )
1477 return WXVARIANT(wxULongLong(0));
1478 if ( valueType
== wxS("wxColour") )
1479 return WXVARIANT(*wxBLACK
);
1481 if ( valueType
== wxPG_VARIANT_TYPE_DATETIME
)
1482 return wxVariant(wxDateTime::Now());
1484 if ( valueType
== wxS("wxFont") )
1485 return WXVARIANT(*wxNORMAL_FONT
);
1486 if ( valueType
== wxS("wxPoint") )
1487 return WXVARIANT(wxPoint(0, 0));
1488 if ( valueType
== wxS("wxSize") )
1489 return WXVARIANT(wxSize(0, 0));
1495 void wxPGProperty::Enable( bool enable
)
1497 wxPropertyGrid
* pg
= GetGrid();
1499 // Preferably call the version in the owning wxPropertyGrid,
1500 // since it handles the editor de-activation.
1502 pg
->EnableProperty(this, enable
);
1507 void wxPGProperty::DoEnable( bool enable
)
1510 ClearFlag(wxPG_PROP_DISABLED
);
1512 SetFlag(wxPG_PROP_DISABLED
);
1514 // Apply same to sub-properties as well
1516 for ( i
= 0; i
< GetChildCount(); i
++ )
1517 Item(i
)->DoEnable( enable
);
1520 void wxPGProperty::EnsureCells( unsigned int column
)
1522 if ( column
>= m_cells
.size() )
1524 // Fill empty slots with default cells
1525 wxPropertyGrid
* pg
= GetGrid();
1526 wxPGCell defaultCell
;
1528 // Work around possible VC6 bug by using intermediate variables
1529 const wxPGCell
& propDefCell
= pg
->GetPropertyDefaultCell();
1530 const wxPGCell
& catDefCell
= pg
->GetCategoryDefaultCell();
1532 if ( !HasFlag(wxPG_PROP_CATEGORY
) )
1533 defaultCell
= propDefCell
;
1535 defaultCell
= catDefCell
;
1537 // TODO: Replace with resize() call
1538 unsigned int cellCountMax
= column
+1;
1540 for ( unsigned int i
=m_cells
.size(); i
<cellCountMax
; i
++ )
1541 m_cells
.push_back(defaultCell
);
1545 void wxPGProperty::SetCell( int column
,
1546 const wxPGCell
& cell
)
1548 EnsureCells(column
);
1550 m_cells
[column
] = cell
;
1553 void wxPGProperty::AdaptiveSetCell( unsigned int firstCol
,
1554 unsigned int lastCol
,
1555 const wxPGCell
& cell
,
1556 const wxPGCell
& srcData
,
1557 wxPGCellData
* unmodCellData
,
1558 FlagType ignoreWithFlags
,
1562 // Sets cell in memory optimizing fashion. That is, if
1563 // current cell data matches unmodCellData, we will
1564 // simply get reference to data from cell. Otherwise,
1565 // cell information from srcData is merged into current.
1568 if ( !(m_flags
& ignoreWithFlags
) && !IsRoot() )
1570 EnsureCells(lastCol
);
1572 for ( unsigned int col
=firstCol
; col
<=lastCol
; col
++ )
1574 if ( m_cells
[col
].GetData() == unmodCellData
)
1576 // Data matches... use cell directly
1577 m_cells
[col
] = cell
;
1581 // Data did not match... merge valid information
1582 m_cells
[col
].MergeFrom(srcData
);
1589 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
1590 Item(i
)->AdaptiveSetCell( firstCol
,
1600 const wxPGCell
& wxPGProperty::GetCell( unsigned int column
) const
1602 if ( m_cells
.size() > column
)
1603 return m_cells
[column
];
1605 wxPropertyGrid
* pg
= GetGrid();
1608 return pg
->GetCategoryDefaultCell();
1610 return pg
->GetPropertyDefaultCell();
1613 wxPGCell
& wxPGProperty::GetOrCreateCell( unsigned int column
)
1615 EnsureCells(column
);
1616 return m_cells
[column
];
1619 void wxPGProperty::SetBackgroundColour( const wxColour
& colour
,
1622 wxPGProperty
* firstProp
= this;
1623 bool recursively
= flags
& wxPG_RECURSE
? true : false;
1626 // If category is tried to set recursively, skip it and only
1627 // affect the children.
1630 while ( firstProp
->IsCategory() )
1632 if ( !firstProp
->GetChildCount() )
1634 firstProp
= firstProp
->Item(0);
1638 wxPGCell
& firstCell
= firstProp
->GetCell(0);
1639 wxPGCellData
* firstCellData
= firstCell
.GetData();
1641 wxPGCell
newCell(firstCell
);
1642 newCell
.SetBgCol(colour
);
1644 srcCell
.SetBgCol(colour
);
1647 GetParentState()->GetColumnCount()-1,
1651 recursively
? wxPG_PROP_CATEGORY
: 0,
1655 void wxPGProperty::SetTextColour( const wxColour
& colour
,
1658 wxPGProperty
* firstProp
= this;
1659 bool recursively
= flags
& wxPG_RECURSE
? true : false;
1662 // If category is tried to set recursively, skip it and only
1663 // affect the children.
1666 while ( firstProp
->IsCategory() )
1668 if ( !firstProp
->GetChildCount() )
1670 firstProp
= firstProp
->Item(0);
1674 wxPGCell
& firstCell
= firstProp
->GetCell(0);
1675 wxPGCellData
* firstCellData
= firstCell
.GetData();
1677 wxPGCell
newCell(firstCell
);
1678 newCell
.SetFgCol(colour
);
1680 srcCell
.SetFgCol(colour
);
1683 GetParentState()->GetColumnCount()-1,
1687 recursively
? wxPG_PROP_CATEGORY
: 0,
1691 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const
1696 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1701 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value
)
1703 if ( DoSetAttribute( name
, value
) )
1705 // Support working without grid, when possible
1706 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1710 m_attributes
.Set( name
, value
);
1713 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes
)
1715 wxPGAttributeStorage::const_iterator it
= attributes
.StartIteration();
1718 while ( attributes
.GetNext(it
, variant
) )
1719 SetAttribute( variant
.GetName(), variant
);
1722 wxVariant
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1728 wxVariant
wxPGProperty::GetAttribute( const wxString
& name
) const
1730 return m_attributes
.FindValue(name
);
1733 wxString
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1735 wxVariant variant
= m_attributes
.FindValue(name
);
1737 if ( !variant
.IsNull() )
1738 return variant
.GetString();
1743 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1745 wxVariant variant
= m_attributes
.FindValue(name
);
1747 if ( variant
.IsNull() )
1750 return variant
.GetLong();
1753 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1755 wxVariant variant
= m_attributes
.FindValue(name
);
1757 if ( variant
.IsNull() )
1760 return variant
.GetDouble();
1763 wxVariant
wxPGProperty::GetAttributesAsList() const
1765 wxVariantList tempList
;
1766 wxVariant
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) );
1768 wxPGAttributeStorage::const_iterator it
= m_attributes
.StartIteration();
1771 while ( m_attributes
.GetNext(it
, variant
) )
1777 // Slots of utility flags are NULL
1778 const unsigned int gs_propFlagToStringSize
= 14;
1780 static const wxChar
* const gs_propFlagToString
[gs_propFlagToStringSize
] = {
1797 wxString
wxPGProperty::GetFlagsAsString( FlagType flagsMask
) const
1800 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1804 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1806 if ( relevantFlags
& a
)
1808 const wxChar
* fs
= gs_propFlagToString
[i
];
1820 void wxPGProperty::SetFlagsFromString( const wxString
& str
)
1824 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1826 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1828 const wxChar
* fs
= gs_propFlagToString
[i
];
1829 if ( fs
&& str
== fs
)
1835 WX_PG_TOKENIZER1_END()
1837 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1840 wxValidator
* wxPGProperty::DoGetValidator() const
1845 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value
)
1847 wxPropertyGrid
* pg
= GetGrid();
1848 int sel
= GetChoiceSelection();
1852 if ( index
== wxNOT_FOUND
)
1853 index
= m_choices
.GetCount();
1858 m_choices
.Insert(label
, index
, value
);
1860 if ( sel
!= newSel
)
1861 SetChoiceSelection(newSel
);
1863 if ( this == pg
->GetSelection() )
1864 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1870 void wxPGProperty::DeleteChoice( int index
)
1872 wxPropertyGrid
* pg
= GetGrid();
1874 int sel
= GetChoiceSelection();
1877 // Adjust current value
1880 SetValueToUnspecified();
1883 else if ( index
< sel
)
1888 m_choices
.RemoveAt(index
);
1890 if ( sel
!= newSel
)
1891 SetChoiceSelection(newSel
);
1893 if ( this == pg
->GetSelection() )
1894 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1897 int wxPGProperty::GetChoiceSelection() const
1899 wxVariant value
= GetValue();
1900 wxString valueType
= value
.GetType();
1901 int index
= wxNOT_FOUND
;
1903 if ( IsValueUnspecified() || !m_choices
.GetCount() )
1906 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1908 index
= value
.GetLong();
1910 else if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1912 index
= m_choices
.Index(value
.GetString());
1914 else if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1916 index
= value
.GetBool()? 1 : 0;
1922 void wxPGProperty::SetChoiceSelection( int newValue
)
1924 // Changes value of a property with choices, but only
1925 // works if the value type is long or string.
1926 wxString valueType
= GetValue().GetType();
1928 wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") );
1930 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1932 SetValue( m_choices
.GetLabel(newValue
) );
1934 else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
1936 SetValue( (long) newValue
);
1940 bool wxPGProperty::SetChoices( const wxPGChoices
& choices
)
1942 // Property must be de-selected first (otherwise choices in
1943 // the control would be de-synced with true choices)
1944 wxPropertyGrid
* pg
= GetGrid();
1945 if ( pg
&& pg
->GetSelection() == this )
1946 pg
->ClearSelection();
1948 m_choices
.Assign(choices
);
1951 // This may be needed to trigger some initialization
1952 // (but don't do it if property is somewhat uninitialized)
1953 wxVariant defVal
= GetDefaultValue();
1954 if ( defVal
.IsNull() )
1964 const wxPGEditor
* wxPGProperty::GetEditorClass() const
1966 const wxPGEditor
* editor
;
1968 if ( !m_customEditor
)
1970 editor
= DoGetEditorClass();
1973 editor
= m_customEditor
;
1976 // Maybe override editor if common value specified
1977 if ( GetDisplayedCommonValueCount() )
1979 // TextCtrlAndButton -> ComboBoxAndButton
1980 if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) )
1981 editor
= wxPGEditor_ChoiceAndButton
;
1983 // TextCtrl -> ComboBox
1984 else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) )
1985 editor
= wxPGEditor_ComboBox
;
1991 bool wxPGProperty::Hide( bool hide
, int flags
)
1993 wxPropertyGrid
* pg
= GetGrid();
1995 return pg
->HideProperty(this, hide
, flags
);
1997 return DoHide( hide
, flags
);
2000 bool wxPGProperty::DoHide( bool hide
, int flags
)
2003 ClearFlag( wxPG_PROP_HIDDEN
);
2005 SetFlag( wxPG_PROP_HIDDEN
);
2007 if ( flags
& wxPG_RECURSE
)
2010 for ( i
= 0; i
< GetChildCount(); i
++ )
2011 Item(i
)->DoHide(hide
, flags
| wxPG_RECURSE_STARTS
);
2017 bool wxPGProperty::HasVisibleChildren() const
2021 for ( i
=0; i
<GetChildCount(); i
++ )
2023 wxPGProperty
* child
= Item(i
);
2025 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
2032 bool wxPGProperty::RecreateEditor()
2034 wxPropertyGrid
* pg
= GetGrid();
2037 wxPGProperty
* selected
= pg
->GetSelection();
2038 if ( this == selected
)
2040 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
2047 void wxPGProperty::SetValueImage( wxBitmap
& bmp
)
2049 delete m_valueBitmap
;
2051 if ( &bmp
&& bmp
.Ok() )
2054 wxSize maxSz
= GetGrid()->GetImageSize();
2055 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
2057 if ( imSz
.y
!= maxSz
.y
)
2059 // Create a memory DC
2060 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
2063 dc
.SelectObject(*bmpNew
);
2066 // FIXME: This is ugly - use image or wait for scaling patch.
2067 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
2069 dc
.SetUserScale(scaleY
, scaleY
);
2071 dc
.DrawBitmap(bmp
, 0, 0);
2073 m_valueBitmap
= bmpNew
;
2077 m_valueBitmap
= new wxBitmap(bmp
);
2080 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
2084 m_valueBitmap
= NULL
;
2085 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
2090 wxPGProperty
* wxPGProperty::GetMainParent() const
2092 const wxPGProperty
* curChild
= this;
2093 const wxPGProperty
* curParent
= m_parent
;
2095 while ( curParent
&& !curParent
->IsCategory() )
2097 curChild
= curParent
;
2098 curParent
= curParent
->m_parent
;
2101 return (wxPGProperty
*) curChild
;
2105 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const
2108 // Returns last visible sub-item, recursively.
2109 if ( !IsExpanded() || !GetChildCount() )
2112 return Last()->GetLastVisibleSubItem();
2116 bool wxPGProperty::IsVisible() const
2118 const wxPGProperty
* parent
;
2120 if ( HasFlag(wxPG_PROP_HIDDEN
) )
2123 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
2125 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
2132 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const
2134 wxPropertyGridPageState
* state
= GetParentState();
2137 wxPropertyGrid
* propGrid
= state
->GetGrid();
2138 if ( state
== propGrid
->GetState() )
2144 int wxPGProperty::GetY2( int lh
) const
2146 const wxPGProperty
* parent
;
2147 const wxPGProperty
* child
= this;
2151 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
2153 if ( !parent
->IsExpanded() )
2155 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
2160 y
-= lh
; // need to reduce one level
2166 int wxPGProperty::GetY() const
2168 return GetY2(GetGrid()->GetRowHeight());
2171 // This is used by Insert etc.
2172 void wxPGProperty::DoAddChild( wxPGProperty
* prop
, int index
,
2175 if ( index
< 0 || (size_t)index
>= m_children
.size() )
2177 if ( correct_mode
) prop
->m_arrIndex
= m_children
.size();
2178 m_children
.push_back( prop
);
2182 m_children
.insert( m_children
.begin()+index
, prop
);
2183 if ( correct_mode
) FixIndicesOfChildren( index
);
2186 prop
->m_parent
= this;
2189 void wxPGProperty::DoPreAddChild( int index
, wxPGProperty
* prop
)
2191 wxASSERT_MSG( prop
->GetBaseName().length(),
2192 "Property's children must have unique, non-empty "
2193 "names within their scope" );
2195 prop
->m_arrIndex
= index
;
2196 m_children
.insert( m_children
.begin()+index
,
2199 int custImgHeight
= prop
->OnMeasureImage().y
;
2200 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
2201 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
2203 prop
->m_parent
= this;
2206 void wxPGProperty::AddPrivateChild( wxPGProperty
* prop
)
2208 if ( !(m_flags
& wxPG_PROP_PARENTAL_FLAGS
) )
2209 SetParentalType(wxPG_PROP_AGGREGATE
);
2211 wxASSERT_MSG( (m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
2212 wxPG_PROP_AGGREGATE
,
2213 "Do not mix up AddPrivateChild() calls with other "
2214 "property adders." );
2216 DoPreAddChild( m_children
.size(), prop
);
2219 #if wxPG_COMPATIBILITY_1_4
2220 void wxPGProperty::AddChild( wxPGProperty
* prop
)
2222 AddPrivateChild(prop
);
2226 wxPGProperty
* wxPGProperty::InsertChild( int index
,
2227 wxPGProperty
* childProperty
)
2230 index
= m_children
.size();
2232 if ( m_parentState
)
2234 m_parentState
->DoInsert(this, index
, childProperty
);
2238 if ( !(m_flags
& wxPG_PROP_PARENTAL_FLAGS
) )
2239 SetParentalType(wxPG_PROP_MISC_PARENT
);
2241 wxASSERT_MSG( (m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
2242 wxPG_PROP_MISC_PARENT
,
2243 "Do not mix up AddPrivateChild() calls with other "
2244 "property adders." );
2246 DoPreAddChild( index
, childProperty
);
2249 return childProperty
;
2252 void wxPGProperty::RemoveChild( wxPGProperty
* p
)
2254 wxArrayPGProperty::iterator it
;
2255 wxArrayPGProperty
& children
= m_children
;
2257 for ( it
=children
.begin(); it
!= children
.end(); it
++ )
2267 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
2269 wxASSERT( GetChildCount() );
2270 wxASSERT( !IsCategory() );
2272 *value
= GetValue();
2274 if ( !list
.GetCount() )
2277 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
2279 bool allChildrenSpecified
;
2281 // Don't fully update aggregate properties unless all children have
2283 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
2284 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
2286 allChildrenSpecified
= true;
2288 wxVariant childValue
= list
[0];
2292 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
2294 for ( i
=0; i
<GetChildCount(); i
++ )
2296 const wxPGProperty
* child
= Item(i
);
2298 if ( childValue
.GetName() == child
->GetBaseName() )
2300 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
2302 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
2304 wxVariant
cv2(child
->GetValue());
2305 child
->AdaptListToValue(childValue
, &cv2
);
2309 if ( allChildrenSpecified
)
2311 *value
= ChildChanged(*value
, i
, childValue
);
2315 if ( n
== (unsigned int)list
.GetCount() )
2317 childValue
= list
[n
];
2323 void wxPGProperty::FixIndicesOfChildren( unsigned int starthere
)
2326 for ( i
=starthere
;i
<GetChildCount();i
++)
2327 Item(i
)->m_arrIndex
= i
;
2331 // Returns (direct) child property with given name (or NULL if not found)
2332 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name
) const
2336 for ( i
=0; i
<GetChildCount(); i
++ )
2338 wxPGProperty
* p
= Item(i
);
2339 if ( p
->m_name
== name
)
2343 // Does it have point, then?
2344 int pos
= name
.Find(wxS('.'));
2348 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
2350 if ( !p
|| !p
->GetChildCount() )
2353 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
2356 wxPGProperty
* wxPGProperty::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex
) const
2358 unsigned int i
= hintIndex
;
2360 if ( i
>= GetChildCount() )
2363 unsigned int lastIndex
= i
- 1;
2365 if ( lastIndex
>= GetChildCount() )
2366 lastIndex
= GetChildCount() - 1;
2370 wxPGProperty
* p
= Item(i
);
2371 if ( p
->m_name
== name
)
2374 if ( i
== lastIndex
)
2378 if ( i
== GetChildCount() )
2385 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_
) const
2387 // Returns height of children, recursively, and
2388 // by taking expanded/collapsed status into account.
2390 // iMax is used when finding property y-positions.
2396 iMax_
= GetChildCount();
2398 unsigned int iMax
= iMax_
;
2400 wxASSERT( iMax
<= GetChildCount() );
2402 if ( !IsExpanded() && GetParent() )
2407 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
2409 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
2411 if ( !pwc
->IsExpanded() ||
2412 pwc
->GetChildCount() == 0 )
2415 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
2424 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
,
2426 unsigned int* nextItemY
) const
2428 wxASSERT( nextItemY
);
2430 // Linear search at the moment
2432 // nextItemY = y of next visible property, final value will be written back.
2433 wxPGProperty
* result
= NULL
;
2434 wxPGProperty
* current
= NULL
;
2435 unsigned int iy
= *nextItemY
;
2437 unsigned int iMax
= GetChildCount();
2441 wxPGProperty
* pwc
= Item(i
);
2443 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
2454 if ( pwc
->IsExpanded() &&
2455 pwc
->GetChildCount() > 0 )
2457 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
2469 if ( !result
&& y
< iy
)
2477 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
2481 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
2485 return (wxPGProperty
*) result
;
2488 void wxPGProperty::Empty()
2491 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
2493 for ( i
=0; i
<GetChildCount(); i
++ )
2495 delete m_children
[i
];
2502 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
) const
2504 unsigned int nextItem
;
2505 return GetItemAtY( y
, GetGrid()->GetRowHeight(), &nextItem
);
2508 void wxPGProperty::DeleteChildren()
2510 wxPropertyGridPageState
* state
= m_parentState
;
2512 if ( !GetChildCount() )
2515 // Because deletion is sometimes deferred, we have to use
2516 // this sort of code for enumerating the child properties.
2517 unsigned int i
= GetChildCount();
2521 state
->DoDelete(Item(i
), true);
2525 wxVariant
wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
2526 int WXUNUSED(childIndex
),
2527 wxVariant
& WXUNUSED(childValue
) ) const
2529 return wxNullVariant
;
2532 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList
) const
2536 const wxVariantList
* pList
= NULL
;
2537 wxVariantList::const_iterator node
;
2541 pList
= &pendingList
->GetList();
2542 node
= pList
->begin();
2545 for ( i
=0; i
<GetChildCount(); i
++ )
2547 wxPGProperty
* child
= Item(i
);
2548 const wxVariant
* listValue
= NULL
;
2553 const wxString
& childName
= child
->GetBaseName();
2555 for ( ; node
!= pList
->end(); ++node
)
2557 const wxVariant
& item
= *((const wxVariant
*)*node
);
2558 if ( item
.GetName() == childName
)
2568 value
= child
->GetValue();
2570 if ( value
.IsNull() )
2573 // Check recursively
2574 if ( child
->GetChildCount() )
2576 const wxVariant
* childList
= NULL
;
2578 if ( listValue
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST
)
2579 childList
= listValue
;
2581 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
2589 wxPGProperty
* wxPGProperty::UpdateParentValues()
2591 wxPGProperty
* parent
= m_parent
;
2592 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
2593 !parent
->IsCategory() && !parent
->IsRoot() )
2596 parent
->DoGenerateComposedValue(s
);
2597 parent
->m_value
= s
;
2598 return parent
->UpdateParentValues();
2603 bool wxPGProperty::IsTextEditable() const
2605 if ( HasFlag(wxPG_PROP_READONLY
) )
2608 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
2610 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
2617 // Call after fixed sub-properties added/removed after creation.
2618 // if oldSelInd >= 0 and < new max items, then selection is
2619 // moved to it. Note: oldSelInd -2 indicates that this property
2620 // should be selected.
2621 void wxPGProperty::SubPropsChanged( int oldSelInd
)
2623 wxPropertyGridPageState
* state
= GetParentState();
2624 wxPropertyGrid
* grid
= state
->GetGrid();
2627 // Re-repare children (recursively)
2628 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
2630 wxPGProperty
* child
= Item(i
);
2631 child
->InitAfterAdded(state
, grid
);
2634 wxPGProperty
* sel
= NULL
;
2635 if ( oldSelInd
>= (int)m_children
.size() )
2636 oldSelInd
= (int)m_children
.size() - 1;
2638 if ( oldSelInd
>= 0 )
2639 sel
= m_children
[oldSelInd
];
2640 else if ( oldSelInd
== -2 )
2644 state
->DoSelectProperty(sel
);
2646 if ( state
== grid
->GetState() )
2648 grid
->GetPanel()->Refresh();
2652 // -----------------------------------------------------------------------
2654 // -----------------------------------------------------------------------
2656 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2657 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2660 wxPGRootProperty::wxPGRootProperty( const wxString
& name
)
2670 wxPGRootProperty::~wxPGRootProperty()
2675 // -----------------------------------------------------------------------
2676 // wxPropertyCategory
2677 // -----------------------------------------------------------------------
2679 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2680 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2682 void wxPropertyCategory::Init()
2684 // don't set colour - prepareadditem method should do this
2685 SetParentalType(wxPG_PROP_CATEGORY
);
2686 m_capFgColIndex
= 1;
2690 wxPropertyCategory::wxPropertyCategory()
2697 wxPropertyCategory::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2698 : wxPGProperty(label
,name
)
2704 wxPropertyCategory::~wxPropertyCategory()
2709 wxString
wxPropertyCategory::ValueToString( wxVariant
& WXUNUSED(value
),
2710 int WXUNUSED(argFlags
) ) const
2712 if ( m_value
.GetType() == wxPG_VARIANT_TYPE_STRING
)
2713 return m_value
.GetString();
2714 return wxEmptyString
;
2717 wxString
wxPropertyCategory::GetValueAsString( int argFlags
) const
2719 #if wxPG_COMPATIBILITY_1_4
2720 // This is backwards compatibility test
2721 // That is, to make sure this function is not overridden
2722 // (instead, ValueToString() should be).
2723 if ( argFlags
== 0xFFFF )
2725 // Do not override! (for backwards compliancy)
2726 return g_invalidStringContent
;
2730 // Unspecified value is always empty string
2731 if ( IsValueUnspecified() )
2732 return wxEmptyString
;
2734 return wxPGProperty::GetValueAsString(argFlags
);
2737 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2739 if ( m_textExtent
> 0 )
2740 return m_textExtent
;
2742 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2746 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2749 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2753 // -----------------------------------------------------------------------
2755 // -----------------------------------------------------------------------
2757 wxPGChoiceEntry
& wxPGChoices::Add( const wxString
& label
, int value
)
2761 wxPGChoiceEntry
entry(label
, value
);
2762 return m_data
->Insert( -1, entry
);
2765 // -----------------------------------------------------------------------
2767 wxPGChoiceEntry
& wxPGChoices::Add( const wxString
& label
, const wxBitmap
& bitmap
, int value
)
2771 wxPGChoiceEntry
entry(label
, value
);
2772 entry
.SetBitmap(bitmap
);
2773 return m_data
->Insert( -1, entry
);
2776 // -----------------------------------------------------------------------
2778 wxPGChoiceEntry
& wxPGChoices::Insert( const wxPGChoiceEntry
& entry
, int index
)
2782 return m_data
->Insert( index
, entry
);
2785 // -----------------------------------------------------------------------
2787 wxPGChoiceEntry
& wxPGChoices::Insert( const wxString
& label
, int index
, int value
)
2791 wxPGChoiceEntry
entry(label
, value
);
2792 return m_data
->Insert( index
, entry
);
2795 // -----------------------------------------------------------------------
2797 wxPGChoiceEntry
& wxPGChoices::AddAsSorted( const wxString
& label
, int value
)
2803 while ( index
< GetCount() )
2805 int cmpRes
= GetLabel(index
).Cmp(label
);
2811 wxPGChoiceEntry
entry(label
, value
);
2812 return m_data
->Insert( index
, entry
);
2815 // -----------------------------------------------------------------------
2817 void wxPGChoices::Add( const wxChar
* const* labels
, const ValArrItem
* values
)
2821 unsigned int itemcount
= 0;
2822 const wxChar
* const* p
= &labels
[0];
2823 while ( *p
) { p
++; itemcount
++; }
2826 for ( i
= 0; i
< itemcount
; i
++ )
2831 wxPGChoiceEntry
entry(labels
[i
], value
);
2832 m_data
->Insert( i
, entry
);
2836 // -----------------------------------------------------------------------
2838 void wxPGChoices::Add( const wxArrayString
& arr
, const wxArrayInt
& arrint
)
2843 unsigned int itemcount
= arr
.size();
2845 for ( i
= 0; i
< itemcount
; i
++ )
2848 if ( &arrint
&& arrint
.size() )
2850 wxPGChoiceEntry
entry(arr
[i
], value
);
2851 m_data
->Insert( i
, entry
);
2855 // -----------------------------------------------------------------------
2857 void wxPGChoices::RemoveAt(size_t nIndex
, size_t count
)
2861 wxASSERT( m_data
->GetRefCount() != -1 );
2862 m_data
->m_items
.erase(m_data
->m_items
.begin()+nIndex
,
2863 m_data
->m_items
.begin()+nIndex
+count
);
2866 // -----------------------------------------------------------------------
2868 void wxPGChoices::Clear()
2870 if ( m_data
!= wxPGChoicesEmptyData
)
2877 // -----------------------------------------------------------------------
2879 int wxPGChoices::Index( const wxString
& str
) const
2884 for ( i
=0; i
< m_data
->GetCount(); i
++ )
2886 const wxPGChoiceEntry
& entry
= m_data
->Item(i
);
2887 if ( entry
.HasText() && entry
.GetText() == str
)
2894 // -----------------------------------------------------------------------
2896 int wxPGChoices::Index( int val
) const
2901 for ( i
=0; i
< m_data
->GetCount(); i
++ )
2903 const wxPGChoiceEntry
& entry
= m_data
->Item(i
);
2904 if ( entry
.GetValue() == val
)
2911 // -----------------------------------------------------------------------
2913 wxArrayString
wxPGChoices::GetLabels() const
2918 if ( this && IsOk() )
2919 for ( i
=0; i
<GetCount(); i
++ )
2920 arr
.push_back(GetLabel(i
));
2925 // -----------------------------------------------------------------------
2927 wxArrayInt
wxPGChoices::GetValuesForStrings( const wxArrayString
& strings
) const
2934 for ( i
=0; i
< strings
.size(); i
++ )
2936 int index
= Index(strings
[i
]);
2938 arr
.Add(GetValue(index
));
2940 arr
.Add(wxPG_INVALID_VALUE
);
2947 // -----------------------------------------------------------------------
2949 wxArrayInt
wxPGChoices::GetIndicesForStrings( const wxArrayString
& strings
,
2950 wxArrayString
* unmatched
) const
2957 for ( i
=0; i
< strings
.size(); i
++ )
2959 const wxString
& str
= strings
[i
];
2960 int index
= Index(str
);
2963 else if ( unmatched
)
2964 unmatched
->Add(str
);
2971 // -----------------------------------------------------------------------
2973 void wxPGChoices::AllocExclusive()
2977 if ( m_data
->GetRefCount() != 1 )
2979 wxPGChoicesData
* data
= new wxPGChoicesData();
2980 data
->CopyDataFrom(m_data
);
2986 // -----------------------------------------------------------------------
2988 void wxPGChoices::AssignData( wxPGChoicesData
* data
)
2992 if ( data
!= wxPGChoicesEmptyData
)
2999 // -----------------------------------------------------------------------
3001 void wxPGChoices::Init()
3003 m_data
= wxPGChoicesEmptyData
;
3006 // -----------------------------------------------------------------------
3008 void wxPGChoices::Free()
3010 if ( m_data
!= wxPGChoicesEmptyData
)
3013 m_data
= wxPGChoicesEmptyData
;
3017 // -----------------------------------------------------------------------
3018 // wxPGAttributeStorage
3019 // -----------------------------------------------------------------------
3021 wxPGAttributeStorage::wxPGAttributeStorage()
3025 wxPGAttributeStorage::~wxPGAttributeStorage()
3027 wxPGHashMapS2P::iterator it
;
3029 for ( it
= m_map
.begin(); it
!= m_map
.end(); ++it
)
3031 wxVariantData
* data
= (wxVariantData
*) it
->second
;
3036 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value
)
3038 wxVariantData
* data
= value
.GetData();
3041 wxPGHashMapS2P::iterator it
= m_map
.find(name
);
3042 if ( it
!= m_map
.end() )
3044 ((wxVariantData
*)it
->second
)->DecRef();
3048 // If Null variant, just remove from set
3062 #endif // wxUSE_PROPGRID