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"
29 #include "wx/window.h"
32 #include "wx/dcmemory.h"
35 #include "wx/settings.h"
41 #include "wx/propgrid/propgrid.h"
44 #define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's
47 #define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing
49 #if wxPG_COMPATIBILITY_1_4
51 // Used to establish backwards compatibility
52 const char* g_invalidStringContent
= "@__TOTALLY_INVALID_STRING__@";
56 // -----------------------------------------------------------------------
58 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect
)
60 #if defined(__WXMSW__) && !defined(__WXWINCE__)
61 // FIXME: Use DrawFocusRect code above (currently it draws solid line
62 // for caption focus but works ok for other stuff).
63 // Also, it seems that this code may not work in future wx versions.
64 dc
.SetLogicalFunction(wxINVERT
);
66 wxPen
pen(*wxBLACK
,1,wxDOT
);
67 pen
.SetCap(wxCAP_BUTT
);
69 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
71 dc
.DrawRectangle(rect
);
73 dc
.SetLogicalFunction(wxCOPY
);
75 dc
.SetLogicalFunction(wxINVERT
);
77 dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
));
78 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
80 dc
.DrawRectangle(rect
);
82 dc
.SetLogicalFunction(wxCOPY
);
86 // -----------------------------------------------------------------------
88 // -----------------------------------------------------------------------
90 wxSize
wxPGCellRenderer::GetImageSize( const wxPGProperty
* WXUNUSED(property
),
92 int WXUNUSED(item
) ) const
97 void wxPGCellRenderer::DrawText( wxDC
& dc
, const wxRect
& rect
,
98 int xOffset
, const wxString
& text
) const
101 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
102 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
105 void wxPGCellRenderer::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
106 int xOffset
, const wxString
& text
,
107 wxPGProperty
* property
,
108 const wxPGEditor
* editor
) const
110 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
117 rect2
.height
-= yOffset
;
118 editor
->DrawValue( dc
, rect2
, property
, text
);
123 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
128 void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
130 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
131 wxPGDrawFocusRect(dc
,focusRect
);
134 int wxPGCellRenderer::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
138 // If possible, use cell colours
139 if ( !(flags
& DontUseCellBgCol
) )
141 const wxColour
& bgCol
= cell
.GetBgCol();
146 if ( !(flags
& DontUseCellFgCol
) )
148 dc
.SetTextForeground(cell
.GetFgCol());
151 // Draw Background, but only if not rendering in control
152 // (as control already has rendered correct background).
153 if ( !(flags
& (Control
|ChoicePopup
)) )
154 dc
.DrawRectangle(rect
);
156 // Use cell font, if provided
157 const wxFont
& font
= cell
.GetFont();
161 const wxBitmap
& bmp
= cell
.GetBitmap();
163 // Do not draw oversized bitmap outside choice popup
164 ((flags
& ChoicePopup
) || bmp
.GetHeight() < rect
.height
)
168 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
169 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
171 imageWidth
= bmp
.GetWidth();
177 void wxPGCellRenderer::PostDrawCell( wxDC
& dc
,
178 const wxPropertyGrid
* propGrid
,
179 const wxPGCell
& cell
,
180 int WXUNUSED(flags
) ) const
183 const wxFont
& font
= cell
.GetFont();
185 dc
.SetFont(propGrid
->GetFont());
188 // -----------------------------------------------------------------------
189 // wxPGDefaultRenderer
190 // -----------------------------------------------------------------------
192 bool wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
,
193 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
194 int column
, int item
, int flags
) const
196 const wxPGEditor
* editor
= NULL
;
197 const wxPGCell
* cell
= NULL
;
200 bool isUnspecified
= property
->IsValueUnspecified();
202 if ( column
== 1 && item
== -1 )
204 int cmnVal
= property
->GetCommonValue();
208 if ( !isUnspecified
)
210 text
= propertyGrid
->GetCommonValueLabel(cmnVal
);
211 DrawText( dc
, rect
, 0, text
);
220 int preDrawFlags
= flags
;
223 property
->GetDisplayInfo(column
, item
, flags
, &text
, &cell
);
225 imageWidth
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
229 editor
= property
->GetColumnEditor(column
);
231 if ( !isUnspecified
)
233 // Regular property value
235 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
237 wxPGPaintData paintdata
;
238 paintdata
.m_parent
= propertyGrid
;
239 paintdata
.m_choiceItem
= item
;
241 if ( imageSize
.x
> 0 )
243 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
244 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
245 wxPG_CUSTOM_IMAGE_WIDTH
,
246 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
248 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
250 paintdata
.m_drawnWidth
= imageSize
.x
;
251 paintdata
.m_drawnHeight
= imageSize
.y
;
253 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
255 imageWidth
= paintdata
.m_drawnWidth
;
258 text
= property
->GetValueAsString();
261 if ( propertyGrid
->GetColumnCount() <= 2 )
263 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
264 if ( !unitsString
.empty() )
265 text
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
271 text
= property
->GetHintText();
276 const wxColour
& hCol
=
277 propertyGrid
->GetCellDisabledTextColour();
278 dc
.SetTextForeground(hCol
);
280 // Must make the editor NULL to override its own rendering
291 int imageOffset
= property
->GetImageOffset(imageWidth
);
293 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
295 // active caption gets nice dotted rectangle
296 if ( property
->IsCategory() && column
== 0 )
298 if ( flags
& Selected
)
300 if ( imageOffset
> 0 )
302 imageOffset
-= DEFAULT_IMAGE_OFFSET_INCREMENT
;
303 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
306 DrawCaptionSelectionRect( dc
,
307 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
308 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
309 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
310 propertyGrid
->GetCaptionFont())
311 +(wxPG_CAPRECTXMARGIN
*2),
312 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
316 PostDrawCell(dc
, propertyGrid
, *cell
, preDrawFlags
);
321 wxSize
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
,
325 if ( property
&& column
== 1 )
329 wxBitmap
* bmp
= property
->GetValueImage();
331 if ( bmp
&& bmp
->IsOk() )
332 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
338 // -----------------------------------------------------------------------
340 // -----------------------------------------------------------------------
342 wxPGCellData::wxPGCellData()
345 m_hasValidText
= false;
348 // -----------------------------------------------------------------------
350 // -----------------------------------------------------------------------
357 wxPGCell::wxPGCell( const wxString
& text
,
358 const wxBitmap
& bitmap
,
359 const wxColour
& fgCol
,
360 const wxColour
& bgCol
)
363 wxPGCellData
* data
= new wxPGCellData();
366 data
->m_bitmap
= bitmap
;
367 data
->m_fgCol
= fgCol
;
368 data
->m_bgCol
= bgCol
;
369 data
->m_hasValidText
= true;
372 wxObjectRefData
*wxPGCell::CloneRefData( const wxObjectRefData
*data
) const
374 wxPGCellData
* c
= new wxPGCellData();
375 const wxPGCellData
* o
= (const wxPGCellData
*) data
;
376 c
->m_text
= o
->m_text
;
377 c
->m_bitmap
= o
->m_bitmap
;
378 c
->m_fgCol
= o
->m_fgCol
;
379 c
->m_bgCol
= o
->m_bgCol
;
380 c
->m_hasValidText
= o
->m_hasValidText
;
384 void wxPGCell::SetText( const wxString
& text
)
388 GetData()->SetText(text
);
391 void wxPGCell::SetBitmap( const wxBitmap
& bitmap
)
395 GetData()->SetBitmap(bitmap
);
398 void wxPGCell::SetFgCol( const wxColour
& col
)
402 GetData()->SetFgCol(col
);
405 void wxPGCell::SetFont( const wxFont
& font
)
409 GetData()->SetFont(font
);
412 void wxPGCell::SetBgCol( const wxColour
& col
)
416 GetData()->SetBgCol(col
);
419 void wxPGCell::MergeFrom( const wxPGCell
& srcCell
)
423 wxPGCellData
* data
= GetData();
425 if ( srcCell
.HasText() )
426 data
->SetText(srcCell
.GetText());
428 if ( srcCell
.GetFgCol().IsOk() )
429 data
->SetFgCol(srcCell
.GetFgCol());
431 if ( srcCell
.GetBgCol().IsOk() )
432 data
->SetBgCol(srcCell
.GetBgCol());
434 if ( srcCell
.GetBitmap().IsOk() )
435 data
->SetBitmap(srcCell
.GetBitmap());
438 void wxPGCell::SetEmptyData()
444 // -----------------------------------------------------------------------
446 // -----------------------------------------------------------------------
448 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
450 wxString
* wxPGProperty::sm_wxPG_LABEL
= NULL
;
452 void wxPGProperty::Init()
458 m_parentState
= NULL
;
461 m_clientObject
= NULL
;
463 m_customEditor
= NULL
;
467 m_valueBitmap
= NULL
;
469 m_maxLen
= 0; // infinite maximum length
471 m_flags
= wxPG_PROP_PROPERTY
;
479 void wxPGProperty::Init( const wxString
& label
, const wxString
& name
)
481 // We really need to check if &label and &name are NULL pointers
482 // (this can if we are called before property grid has been initalized)
484 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
487 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
490 DoSetName( m_label
);
495 void wxPGProperty::InitAfterAdded( wxPropertyGridPageState
* pageState
,
496 wxPropertyGrid
* propgrid
)
499 // Called after property has been added to grid or page
500 // (so propgrid can be NULL, too).
502 wxPGProperty
* parent
= m_parent
;
503 bool parentIsRoot
= parent
->IsKindOf(wxCLASSINFO(wxPGRootProperty
));
506 // Convert invalid cells to default ones in this grid
507 for ( unsigned int i
=0; i
<m_cells
.size(); i
++ )
509 wxPGCell
& cell
= m_cells
[i
];
510 if ( cell
.IsInvalid() )
512 const wxPGCell
& propDefCell
= propgrid
->GetPropertyDefaultCell();
513 const wxPGCell
& catDefCell
= propgrid
->GetCategoryDefaultCell();
515 if ( !HasFlag(wxPG_PROP_CATEGORY
) )
522 m_parentState
= pageState
;
524 #if wxPG_COMPATIBILITY_1_4
525 // Make sure deprecated virtual functions are not implemented
526 wxString s
= GetValueAsString( 0xFFFF );
527 wxASSERT_MSG( s
== g_invalidStringContent
,
528 "Implement ValueToString() instead of GetValueAsString()" );
531 if ( !parentIsRoot
&& !parent
->IsCategory() )
533 m_cells
= parent
->m_cells
;
536 // If in hideable adding mode, or if assigned parent is hideable, then
537 // make this one hideable.
539 ( !parentIsRoot
&& parent
->HasFlag(wxPG_PROP_HIDDEN
) ) ||
540 ( propgrid
&& (propgrid
->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES
)) )
542 SetFlag( wxPG_PROP_HIDDEN
);
544 // Set custom image flag.
545 int custImgHeight
= OnMeasureImage().y
;
546 if ( custImgHeight
< 0 )
548 SetFlag(wxPG_PROP_CUSTOMIMAGE
);
551 if ( propgrid
&& (propgrid
->HasFlag(wxPG_LIMITED_EDITING
)) )
552 SetFlag(wxPG_PROP_NOEDITOR
);
554 // Make sure parent has some parental flags
555 if ( !parent
->HasFlag(wxPG_PROP_PARENTAL_FLAGS
) )
556 parent
->SetParentalType(wxPG_PROP_MISC_PARENT
);
560 // This is not a category.
564 unsigned char depth
= 1;
567 depth
= parent
->m_depth
;
568 if ( !parent
->IsCategory() )
572 unsigned char greyDepth
= depth
;
576 wxPropertyCategory
* pc
;
578 if ( parent
->IsCategory() )
579 pc
= (wxPropertyCategory
* ) parent
;
581 // This conditional compile is necessary to
582 // bypass some compiler bug.
583 pc
= pageState
->GetPropertyCategory(parent
);
586 greyDepth
= pc
->GetDepth();
588 greyDepth
= parent
->m_depthBgCol
;
591 m_depthBgCol
= greyDepth
;
595 // This is a category.
598 unsigned char depth
= 1;
601 depth
= parent
->m_depth
+ 1;
604 m_depthBgCol
= depth
;
608 // Has initial children
609 if ( GetChildCount() )
611 // Check parental flags
612 wxASSERT_MSG( ((m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
613 wxPG_PROP_AGGREGATE
) ||
614 ((m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
615 wxPG_PROP_MISC_PARENT
),
616 "wxPGProperty parental flags set incorrectly at "
619 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
621 // Properties with private children are not expanded by default.
624 else if ( propgrid
&& propgrid
->HasFlag(wxPG_HIDE_MARGIN
) )
626 // ...unless it cannot be expanded by user and therefore must
627 // remain visible at all times
632 // Prepare children recursively
633 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
635 wxPGProperty
* child
= Item(i
);
636 child
->InitAfterAdded(pageState
, pageState
->GetGrid());
639 if ( propgrid
&& (propgrid
->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES
) )
640 SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED
, true);
644 void wxPGProperty::OnDetached(wxPropertyGridPageState
* WXUNUSED(state
),
645 wxPropertyGrid
* propgrid
)
649 const wxPGCell
& propDefCell
= propgrid
->GetPropertyDefaultCell();
650 const wxPGCell
& catDefCell
= propgrid
->GetCategoryDefaultCell();
652 // Make default cells invalid
653 for ( unsigned int i
=0; i
<m_cells
.size(); i
++ )
655 wxPGCell
& cell
= m_cells
[i
];
656 if ( cell
.IsSameAs(propDefCell
) ||
657 cell
.IsSameAs(catDefCell
) )
665 wxPGProperty::wxPGProperty()
672 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name
)
679 wxPGProperty::~wxPGProperty()
681 delete m_clientObject
;
683 Empty(); // this deletes items
685 delete m_valueBitmap
;
690 // This makes it easier for us to detect dangling pointers
695 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate
) const
697 wxPGProperty
* parent
= m_parent
;
700 if ( parent
== candidate
)
702 parent
= parent
->m_parent
;
707 void wxPGProperty::SetName( const wxString
& newName
)
709 wxPropertyGrid
* pg
= GetGrid();
712 pg
->SetPropertyName(this, newName
);
717 wxString
wxPGProperty::GetName() const
719 wxPGProperty
* parent
= GetParent();
721 if ( m_name
.empty() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
724 return m_parent
->GetName() + wxS(".") + m_name
;
727 wxPropertyGrid
* wxPGProperty::GetGrid() const
729 if ( !m_parentState
)
731 return m_parentState
->GetGrid();
734 int wxPGProperty::Index( const wxPGProperty
* p
) const
736 return wxPGFindInVector(m_children
, p
);
739 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
744 void wxPGProperty::OnSetValue()
748 void wxPGProperty::RefreshChildren ()
752 void wxPGProperty::OnValidationFailure( wxVariant
& WXUNUSED(pendingValue
) )
756 void wxPGProperty::GetDisplayInfo( unsigned int column
,
760 const wxPGCell
** pCell
)
762 const wxPGCell
* cell
= NULL
;
764 if ( !(flags
& wxPGCellRenderer::ChoicePopup
) )
766 // Not painting list of choice popups, so get text from property
767 if ( column
!= 1 || !IsValueUnspecified() || IsCategory() )
769 cell
= &GetCell(column
);
773 // Use special unspecified value cell
774 cell
= &GetGrid()->GetUnspecifiedValueAppearance();
777 if ( cell
->HasText() )
779 *pString
= cell
->GetText();
784 *pString
= GetLabel();
785 else if ( column
== 1 )
786 *pString
= GetDisplayedString();
787 else if ( column
== 2 )
788 *pString
= GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
793 wxASSERT( column
== 1 );
795 if ( choiceIndex
!= wxNOT_FOUND
)
797 const wxPGChoiceEntry
& entry
= m_choices
[choiceIndex
];
798 if ( entry
.GetBitmap().IsOk() ||
799 entry
.GetFgCol().IsOk() ||
800 entry
.GetBgCol().IsOk() )
802 *pString
= m_choices
.GetLabel(choiceIndex
);
807 cell
= &GetCell(column
);
809 wxASSERT_MSG( cell
->GetData(),
810 wxString::Format("Invalid cell for property %s",
811 GetName().c_str()) );
817 wxString wxPGProperty::GetColumnText( unsigned int col, int choiceIndex ) const
820 if ( col != 1 || choiceIndex == wxNOT_FOUND )
822 const wxPGCell& cell = GetCell(col);
823 if ( cell->HasText() )
825 return cell->GetText();
832 return GetDisplayedString();
834 return GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString);
840 return m_choices.GetLabel(choiceIndex);
843 return wxEmptyString;
847 void wxPGProperty::DoGenerateComposedValue( wxString
& text
,
849 const wxVariantList
* valueOverrides
,
850 wxPGHashMapS2S
* childResults
) const
853 int iMax
= m_children
.size();
859 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
860 !(argFlags
& wxPG_FULL_VALUE
) )
861 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
863 int iMaxMinusOne
= iMax
-1;
865 if ( !IsTextEditable() )
866 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
868 wxPGProperty
* curChild
= m_children
[0];
870 bool overridesLeft
= false;
871 wxVariant overrideValue
;
872 wxVariantList::const_iterator node
;
874 if ( valueOverrides
)
876 node
= valueOverrides
->begin();
877 if ( node
!= valueOverrides
->end() )
879 overrideValue
= *node
;
880 overridesLeft
= true;
884 for ( i
= 0; i
< iMax
; i
++ )
886 wxVariant childValue
;
888 wxString childLabel
= curChild
->GetLabel();
890 // Check for value override
891 if ( overridesLeft
&& overrideValue
.GetName() == childLabel
)
893 if ( !overrideValue
.IsNull() )
894 childValue
= overrideValue
;
896 childValue
= curChild
->GetValue();
898 if ( node
!= valueOverrides
->end() )
899 overrideValue
= *node
;
901 overridesLeft
= false;
905 childValue
= curChild
->GetValue();
909 if ( !childValue
.IsNull() )
911 if ( overridesLeft
&&
912 curChild
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
913 childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
915 wxVariantList
& childList
= childValue
.GetList();
916 DoGenerateComposedValue(s
, argFlags
|wxPG_COMPOSITE_FRAGMENT
,
917 &childList
, childResults
);
921 s
= curChild
->ValueToString(childValue
,
922 argFlags
|wxPG_COMPOSITE_FRAGMENT
);
926 if ( childResults
&& curChild
->GetChildCount() )
927 (*childResults
)[curChild
->GetName()] = s
;
930 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && s
.empty() )
933 if ( !curChild
->GetChildCount() || skip
)
936 text
+= wxS("[") + s
+ wxS("]");
938 if ( i
< iMaxMinusOne
)
940 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
941 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
942 !(argFlags
& wxPG_FULL_VALUE
) )
947 if ( !curChild
->GetChildCount() )
953 curChild
= m_children
[i
+1];
957 if ( (unsigned int)i
< m_children
.size() )
959 if ( !text
.EndsWith(wxS("; ")) )
960 text
+= wxS("; ...");
966 wxString
wxPGProperty::ValueToString( wxVariant
& WXUNUSED(value
),
969 wxCHECK_MSG( GetChildCount() > 0,
971 "If user property does not have any children, it must "
972 "override GetValueAsString" );
974 // FIXME: Currently code below only works if value is actually m_value
975 wxASSERT_MSG( argFlags
& wxPG_VALUE_IS_CURRENT
,
976 "Sorry, currently default wxPGProperty::ValueToString() "
977 "implementation only works if value is m_value." );
980 DoGenerateComposedValue(text
, argFlags
);
984 wxString
wxPGProperty::GetValueAsString( int argFlags
) const
986 #if wxPG_COMPATIBILITY_1_4
987 // This is backwards compatibility test
988 // That is, to make sure this function is not overridden
989 // (instead, ValueToString() should be).
990 if ( argFlags
== 0xFFFF )
992 // Do not override! (for backwards compliancy)
993 return g_invalidStringContent
;
997 wxPropertyGrid
* pg
= GetGrid();
999 if ( IsValueUnspecified() )
1000 return pg
->GetUnspecifiedValueText(argFlags
);
1002 if ( m_commonValue
== -1 )
1004 wxVariant
value(GetValue());
1005 return ValueToString(value
, argFlags
|wxPG_VALUE_IS_CURRENT
);
1009 // Return common value's string representation
1010 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
1012 if ( argFlags
& wxPG_FULL_VALUE
)
1014 return cv
->GetLabel();
1016 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
1018 return cv
->GetEditableText();
1022 return cv
->GetLabel();
1026 wxString
wxPGProperty::GetValueString( int argFlags
) const
1028 return GetValueAsString(argFlags
);
1031 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
1033 variant
= (long)number
;
1037 // Convert semicolon delimited tokens into child values.
1038 bool wxPGProperty::StringToValue( wxVariant
& v
, const wxString
& text
, int argFlags
) const
1040 if ( !GetChildCount() )
1043 unsigned int curChild
= 0;
1045 unsigned int iMax
= m_children
.size();
1047 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
1048 !(argFlags
& wxPG_FULL_VALUE
) )
1049 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
1051 bool changed
= false;
1056 // Its best only to add non-empty group items
1057 bool addOnlyIfNotEmpty
= false;
1058 const wxChar delimeter
= wxS(';');
1060 size_t tokenStart
= 0xFFFFFF;
1062 wxVariantList temp_list
;
1063 wxVariant
list(temp_list
);
1065 int propagatedFlags
= argFlags
& (wxPG_REPORT_ERROR
|wxPG_PROGRAMMATIC_VALUE
);
1067 wxLogTrace("propgrid",
1068 wxT(">> %s.StringToValue('%s')"), GetLabel(), text
);
1070 wxString::const_iterator it
= text
.begin();
1073 if ( it
!= text
.end() )
1080 // How many units we iterate string forward at the end of loop?
1081 // We need to keep track of this or risk going to negative
1082 // with it-- operation.
1083 unsigned int strPosIncrement
= 1;
1085 if ( tokenStart
!= 0xFFFFFF )
1088 if ( a
== delimeter
|| a
== 0 )
1090 token
= text
.substr(tokenStart
,pos
-tokenStart
);
1092 size_t len
= token
.length();
1094 if ( !addOnlyIfNotEmpty
|| len
> 0 )
1096 const wxPGProperty
* child
= Item(curChild
);
1097 wxVariant
variant(child
->GetValue());
1098 wxString childName
= child
->GetBaseName();
1100 wxLogTrace("propgrid",
1101 wxT("token = '%s', child = %s"),
1104 // Add only if editable or setting programmatically
1105 if ( (argFlags
& wxPG_PROGRAMMATIC_VALUE
) ||
1106 (!child
->HasFlag(wxPG_PROP_DISABLED
) &&
1107 !child
->HasFlag(wxPG_PROP_READONLY
)) )
1111 if ( child
->StringToValue(variant
, token
,
1112 propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
1114 // We really need to set the variant's name
1115 // *after* child->StringToValue() has been
1116 // called, since variant's value may be set by
1117 // assigning another variant into it, which
1118 // then usually causes name to be copied (ie.
1119 // usually cleared) as well. wxBoolProperty
1120 // being case in point with its use of
1121 // wxPGVariant_Bool macro as an optimization.
1122 variant
.SetName(childName
);
1123 list
.Append(variant
);
1130 // Empty, becomes unspecified
1132 variant
.SetName(childName
);
1133 list
.Append(variant
);
1139 if ( curChild
>= iMax
)
1143 tokenStart
= 0xFFFFFF;
1148 // Token is not running
1149 if ( a
!= wxS(' ') )
1152 addOnlyIfNotEmpty
= false;
1154 // Is this a group of tokens?
1155 if ( a
== wxS('[') )
1159 if ( it
!= text
.end() ) ++it
;
1161 size_t startPos
= pos
;
1163 // Group item - find end
1164 while ( it
!= text
.end() && depth
> 0 )
1170 if ( a
== wxS(']') )
1172 else if ( a
== wxS('[') )
1176 token
= text
.substr(startPos
,pos
-startPos
-1);
1178 if ( token
.empty() )
1181 const wxPGProperty
* child
= Item(curChild
);
1183 wxVariant oldChildValue
= child
->GetValue();
1184 wxVariant
variant(oldChildValue
);
1186 if ( (argFlags
& wxPG_PROGRAMMATIC_VALUE
) ||
1187 (!child
->HasFlag(wxPG_PROP_DISABLED
) &&
1188 !child
->HasFlag(wxPG_PROP_READONLY
)) )
1190 wxString childName
= child
->GetBaseName();
1192 bool stvRes
= child
->StringToValue( variant
, token
,
1194 if ( stvRes
|| (variant
!= oldChildValue
) )
1196 variant
.SetName(childName
);
1197 list
.Append(variant
);
1208 if ( curChild
>= iMax
)
1211 addOnlyIfNotEmpty
= true;
1213 tokenStart
= 0xFFFFFF;
1219 if ( a
== delimeter
)
1220 strPosIncrement
-= 1;
1228 it
+= strPosIncrement
;
1230 if ( it
!= text
.end() )
1239 pos
+= strPosIncrement
;
1248 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags
)
1250 wxVariant
variant(m_value
);
1251 bool res
= StringToValue(variant
, text
, argFlags
);
1257 bool wxPGProperty::SetValueFromInt( long number
, int argFlags
)
1259 wxVariant
variant(m_value
);
1260 bool res
= IntToValue(variant
, number
, argFlags
);
1266 wxSize
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const
1268 if ( m_valueBitmap
)
1269 return wxSize(m_valueBitmap
->GetWidth(),-1);
1274 int wxPGProperty::GetImageOffset( int imageWidth
) const
1276 int imageOffset
= 0;
1280 // Do not increment offset too much for wide images
1281 if ( imageWidth
<= (wxPG_CUSTOM_IMAGE_WIDTH
+5) )
1282 imageOffset
= imageWidth
+ DEFAULT_IMAGE_OFFSET_INCREMENT
;
1284 imageOffset
= imageWidth
+ 1;
1290 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const
1292 return wxPGGlobalVars
->m_defaultRenderer
;
1295 void wxPGProperty::OnCustomPaint( wxDC
& dc
,
1299 wxBitmap
* bmp
= m_valueBitmap
;
1301 wxCHECK_RET( bmp
&& bmp
->IsOk(), wxT("invalid bitmap") );
1303 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
1305 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
1308 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const
1310 return wxPGEditor_TextCtrl
;
1313 // Default extra property event handling - that is, none at all.
1314 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
1320 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
1322 // If auto unspecified values are not wanted (via window or property style),
1323 // then get default value instead of wxNullVariant.
1324 if ( value
.IsNull() && (flags
& wxPG_SETVAL_BY_USER
) &&
1325 !UsesAutoUnspecified() )
1327 value
= GetDefaultValue();
1330 if ( !value
.IsNull() )
1332 wxVariant tempListVariant
;
1335 // List variants are reserved a special purpose
1336 // as intermediate containers for child values
1337 // of properties with children.
1338 if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1341 // However, situation is different for composed string properties
1342 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
1344 tempListVariant
= value
;
1345 pList
= &tempListVariant
;
1349 AdaptListToValue(value
, &newValue
);
1351 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
1354 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
1355 flags
|= wxPG_SETVAL_AGGREGATED
;
1357 if ( pList
&& !pList
->IsNull() )
1359 wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST
);
1360 wxASSERT( GetChildCount() );
1361 wxASSERT( !IsCategory() );
1363 wxVariantList
& list
= pList
->GetList();
1364 wxVariantList::iterator node
;
1367 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
1369 // Children in list can be in any order, but we will give hint to
1370 // GetPropertyByNameWH(). This optimizes for full list parsing.
1371 for ( node
= list
.begin(); node
!= list
.end(); ++node
)
1373 wxVariant
& childValue
= *((wxVariant
*)*node
);
1374 wxPGProperty
* child
= GetPropertyByNameWH(childValue
.GetName(), i
);
1377 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
1378 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1380 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
1382 wxVariant listRefCopy
= childValue
;
1383 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
1387 wxVariant oldVal
= child
->GetValue();
1388 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
1391 else if ( child
->GetValue() != childValue
)
1393 // For aggregate properties, we will trust RefreshChildren()
1394 // to update child values.
1395 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
1396 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1397 if ( flags
& wxPG_SETVAL_BY_USER
)
1398 child
->SetFlag(wxPG_PROP_MODIFIED
);
1404 // Always call OnSetValue() for a parent property (do not call it
1405 // here if the value is non-null because it will then be called
1407 if ( value
.IsNull() )
1411 if ( !value
.IsNull() )
1417 if ( flags
& wxPG_SETVAL_BY_USER
)
1418 SetFlag(wxPG_PROP_MODIFIED
);
1420 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1425 if ( m_commonValue
!= -1 )
1427 wxPropertyGrid
* pg
= GetGrid();
1428 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
1434 // Set children to unspecified, but only if aggregate or
1435 // value is <composed>
1436 if ( AreChildrenComponents() )
1439 for ( i
=0; i
<GetChildCount(); i
++ )
1440 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1444 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
1445 UpdateParentValues();
1448 // Update editor control.
1449 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1451 wxPropertyGrid
* pg
= GetGridIfDisplayed();
1454 wxPGProperty
* selected
= pg
->GetSelectedProperty();
1456 // Only refresh the control if this was selected, or
1457 // this was some parent of selected, or vice versa)
1458 if ( selected
&& (selected
== this ||
1459 selected
->IsSomeParent(this) ||
1460 this->IsSomeParent(selected
)) )
1463 pg
->DrawItemAndValueRelated(this);
1469 void wxPGProperty::SetValueInEvent( wxVariant value
) const
1471 GetGrid()->ValueChangeInEvent(value
);
1474 void wxPGProperty::SetFlagRecursively( wxPGPropertyFlags flag
, bool set
)
1476 ChangeFlag(flag
, set
);
1479 for ( i
= 0; i
< GetChildCount(); i
++ )
1480 Item(i
)->SetFlagRecursively(flag
, set
);
1483 void wxPGProperty::RefreshEditor()
1488 wxPropertyGrid
* pg
= GetGrid();
1489 if ( pg
&& pg
->GetSelectedProperty() == this )
1490 pg
->RefreshEditor();
1493 wxVariant
wxPGProperty::GetDefaultValue() const
1495 wxVariant defVal
= GetAttribute(wxPG_ATTR_DEFAULT_VALUE
);
1496 if ( !defVal
.IsNull() )
1499 wxVariant value
= GetValue();
1501 if ( !value
.IsNull() )
1503 wxString
valueType(value
.GetType());
1505 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1506 return wxPGVariant_Zero
;
1507 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1508 return wxPGVariant_EmptyString
;
1509 if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1510 return wxPGVariant_False
;
1511 if ( valueType
== wxPG_VARIANT_TYPE_DOUBLE
)
1512 return wxVariant(0.0);
1513 if ( valueType
== wxPG_VARIANT_TYPE_ARRSTRING
)
1514 return wxVariant(wxArrayString());
1515 if ( valueType
== wxS("wxLongLong") )
1516 return WXVARIANT(wxLongLong(0));
1517 if ( valueType
== wxS("wxULongLong") )
1518 return WXVARIANT(wxULongLong(0));
1519 if ( valueType
== wxS("wxColour") )
1520 return WXVARIANT(*wxBLACK
);
1522 if ( valueType
== wxPG_VARIANT_TYPE_DATETIME
)
1523 return wxVariant(wxDateTime::Now());
1525 if ( valueType
== wxS("wxFont") )
1526 return WXVARIANT(*wxNORMAL_FONT
);
1527 if ( valueType
== wxS("wxPoint") )
1528 return WXVARIANT(wxPoint(0, 0));
1529 if ( valueType
== wxS("wxSize") )
1530 return WXVARIANT(wxSize(0, 0));
1536 void wxPGProperty::Enable( bool enable
)
1538 wxPropertyGrid
* pg
= GetGrid();
1540 // Preferably call the version in the owning wxPropertyGrid,
1541 // since it handles the editor de-activation.
1543 pg
->EnableProperty(this, enable
);
1548 void wxPGProperty::DoEnable( bool enable
)
1551 ClearFlag(wxPG_PROP_DISABLED
);
1553 SetFlag(wxPG_PROP_DISABLED
);
1555 // Apply same to sub-properties as well
1557 for ( i
= 0; i
< GetChildCount(); i
++ )
1558 Item(i
)->DoEnable( enable
);
1561 void wxPGProperty::EnsureCells( unsigned int column
)
1563 if ( column
>= m_cells
.size() )
1565 // Fill empty slots with default cells
1566 wxPropertyGrid
* pg
= GetGrid();
1567 wxPGCell defaultCell
;
1571 // Work around possible VC6 bug by using intermediate variables
1572 const wxPGCell
& propDefCell
= pg
->GetPropertyDefaultCell();
1573 const wxPGCell
& catDefCell
= pg
->GetCategoryDefaultCell();
1575 if ( !HasFlag(wxPG_PROP_CATEGORY
) )
1576 defaultCell
= propDefCell
;
1578 defaultCell
= catDefCell
;
1581 // TODO: Replace with resize() call
1582 unsigned int cellCountMax
= column
+1;
1584 for ( unsigned int i
=m_cells
.size(); i
<cellCountMax
; i
++ )
1585 m_cells
.push_back(defaultCell
);
1589 void wxPGProperty::SetCell( int column
,
1590 const wxPGCell
& cell
)
1592 EnsureCells(column
);
1594 m_cells
[column
] = cell
;
1597 void wxPGProperty::AdaptiveSetCell( unsigned int firstCol
,
1598 unsigned int lastCol
,
1599 const wxPGCell
& cell
,
1600 const wxPGCell
& srcData
,
1601 wxPGCellData
* unmodCellData
,
1602 FlagType ignoreWithFlags
,
1606 // Sets cell in memory optimizing fashion. That is, if
1607 // current cell data matches unmodCellData, we will
1608 // simply get reference to data from cell. Otherwise,
1609 // cell information from srcData is merged into current.
1612 if ( !(m_flags
& ignoreWithFlags
) && !IsRoot() )
1614 EnsureCells(lastCol
);
1616 for ( unsigned int col
=firstCol
; col
<=lastCol
; col
++ )
1618 if ( m_cells
[col
].GetData() == unmodCellData
)
1620 // Data matches... use cell directly
1621 m_cells
[col
] = cell
;
1625 // Data did not match... merge valid information
1626 m_cells
[col
].MergeFrom(srcData
);
1633 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
1634 Item(i
)->AdaptiveSetCell( firstCol
,
1644 const wxPGCell
& wxPGProperty::GetCell( unsigned int column
) const
1646 if ( m_cells
.size() > column
)
1647 return m_cells
[column
];
1649 wxPropertyGrid
* pg
= GetGrid();
1652 return pg
->GetCategoryDefaultCell();
1654 return pg
->GetPropertyDefaultCell();
1657 wxPGCell
& wxPGProperty::GetOrCreateCell( unsigned int column
)
1659 EnsureCells(column
);
1660 return m_cells
[column
];
1663 void wxPGProperty::SetBackgroundColour( const wxColour
& colour
,
1666 wxPGProperty
* firstProp
= this;
1667 bool recursively
= flags
& wxPG_RECURSE
? true : false;
1670 // If category is tried to set recursively, skip it and only
1671 // affect the children.
1674 while ( firstProp
->IsCategory() )
1676 if ( !firstProp
->GetChildCount() )
1678 firstProp
= firstProp
->Item(0);
1682 wxPGCell
& firstCell
= firstProp
->GetCell(0);
1683 wxPGCellData
* firstCellData
= firstCell
.GetData();
1685 wxPGCell
newCell(firstCell
);
1686 newCell
.SetBgCol(colour
);
1688 srcCell
.SetBgCol(colour
);
1691 GetParentState()->GetColumnCount()-1,
1695 recursively
? wxPG_PROP_CATEGORY
: 0,
1699 void wxPGProperty::SetTextColour( const wxColour
& colour
,
1702 wxPGProperty
* firstProp
= this;
1703 bool recursively
= flags
& wxPG_RECURSE
? true : false;
1706 // If category is tried to set recursively, skip it and only
1707 // affect the children.
1710 while ( firstProp
->IsCategory() )
1712 if ( !firstProp
->GetChildCount() )
1714 firstProp
= firstProp
->Item(0);
1718 wxPGCell
& firstCell
= firstProp
->GetCell(0);
1719 wxPGCellData
* firstCellData
= firstCell
.GetData();
1721 wxPGCell
newCell(firstCell
);
1722 newCell
.SetFgCol(colour
);
1724 srcCell
.SetFgCol(colour
);
1727 GetParentState()->GetColumnCount()-1,
1731 recursively
? wxPG_PROP_CATEGORY
: 0,
1735 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const
1740 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1745 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value
)
1747 if ( DoSetAttribute( name
, value
) )
1749 // Support working without grid, when possible
1750 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1754 m_attributes
.Set( name
, value
);
1757 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes
)
1759 wxPGAttributeStorage::const_iterator it
= attributes
.StartIteration();
1762 while ( attributes
.GetNext(it
, variant
) )
1763 SetAttribute( variant
.GetName(), variant
);
1766 wxVariant
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1772 wxVariant
wxPGProperty::GetAttribute( const wxString
& name
) const
1774 return m_attributes
.FindValue(name
);
1777 wxString
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1779 wxVariant variant
= m_attributes
.FindValue(name
);
1781 if ( !variant
.IsNull() )
1782 return variant
.GetString();
1787 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1789 wxVariant variant
= m_attributes
.FindValue(name
);
1791 if ( variant
.IsNull() )
1794 return variant
.GetLong();
1797 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1799 wxVariant variant
= m_attributes
.FindValue(name
);
1801 if ( variant
.IsNull() )
1804 return variant
.GetDouble();
1807 wxVariant
wxPGProperty::GetAttributesAsList() const
1809 wxVariantList tempList
;
1810 wxVariant
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) );
1812 wxPGAttributeStorage::const_iterator it
= m_attributes
.StartIteration();
1815 while ( m_attributes
.GetNext(it
, variant
) )
1821 // Slots of utility flags are NULL
1822 const unsigned int gs_propFlagToStringSize
= 14;
1824 static const wxChar
* const gs_propFlagToString
[gs_propFlagToStringSize
] = {
1841 wxString
wxPGProperty::GetFlagsAsString( FlagType flagsMask
) const
1844 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1848 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1850 if ( relevantFlags
& a
)
1852 const wxChar
* fs
= gs_propFlagToString
[i
];
1864 void wxPGProperty::SetFlagsFromString( const wxString
& str
)
1868 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1870 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1872 const wxChar
* fs
= gs_propFlagToString
[i
];
1873 if ( fs
&& str
== fs
)
1879 WX_PG_TOKENIZER1_END()
1881 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1884 wxValidator
* wxPGProperty::DoGetValidator() const
1889 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value
)
1891 wxPropertyGrid
* pg
= GetGrid();
1892 int sel
= GetChoiceSelection();
1896 if ( index
== wxNOT_FOUND
)
1897 index
= m_choices
.GetCount();
1902 m_choices
.Insert(label
, index
, value
);
1904 if ( sel
!= newSel
)
1905 SetChoiceSelection(newSel
);
1907 if ( this == pg
->GetSelection() )
1908 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1914 void wxPGProperty::DeleteChoice( int index
)
1916 wxPropertyGrid
* pg
= GetGrid();
1918 int sel
= GetChoiceSelection();
1921 // Adjust current value
1924 SetValueToUnspecified();
1927 else if ( index
< sel
)
1932 m_choices
.RemoveAt(index
);
1934 if ( sel
!= newSel
)
1935 SetChoiceSelection(newSel
);
1937 if ( this == pg
->GetSelection() )
1938 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1941 int wxPGProperty::GetChoiceSelection() const
1943 wxVariant value
= GetValue();
1944 wxString valueType
= value
.GetType();
1945 int index
= wxNOT_FOUND
;
1947 if ( IsValueUnspecified() || !m_choices
.GetCount() )
1950 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1952 index
= value
.GetLong();
1954 else if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1956 index
= m_choices
.Index(value
.GetString());
1958 else if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1960 index
= value
.GetBool()? 1 : 0;
1966 void wxPGProperty::SetChoiceSelection( int newValue
)
1968 // Changes value of a property with choices, but only
1969 // works if the value type is long or string.
1970 wxString valueType
= GetValue().GetType();
1972 wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") );
1974 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1976 SetValue( m_choices
.GetLabel(newValue
) );
1978 else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
1980 SetValue( (long) newValue
);
1984 bool wxPGProperty::SetChoices( const wxPGChoices
& choices
)
1986 // Property must be de-selected first (otherwise choices in
1987 // the control would be de-synced with true choices)
1988 wxPropertyGrid
* pg
= GetGrid();
1989 if ( pg
&& pg
->GetSelection() == this )
1990 pg
->ClearSelection();
1992 m_choices
.Assign(choices
);
1995 // This may be needed to trigger some initialization
1996 // (but don't do it if property is somewhat uninitialized)
1997 wxVariant defVal
= GetDefaultValue();
1998 if ( defVal
.IsNull() )
2008 const wxPGEditor
* wxPGProperty::GetEditorClass() const
2010 const wxPGEditor
* editor
;
2012 if ( !m_customEditor
)
2014 editor
= DoGetEditorClass();
2017 editor
= m_customEditor
;
2020 // Maybe override editor if common value specified
2021 if ( GetDisplayedCommonValueCount() )
2023 // TextCtrlAndButton -> ComboBoxAndButton
2024 if ( wxDynamicCast(editor
, wxPGTextCtrlAndButtonEditor
) )
2025 editor
= wxPGEditor_ChoiceAndButton
;
2027 // TextCtrl -> ComboBox
2028 else if ( wxDynamicCast(editor
, wxPGTextCtrlEditor
) )
2029 editor
= wxPGEditor_ComboBox
;
2035 bool wxPGProperty::Hide( bool hide
, int flags
)
2037 wxPropertyGrid
* pg
= GetGrid();
2039 return pg
->HideProperty(this, hide
, flags
);
2041 return DoHide( hide
, flags
);
2044 bool wxPGProperty::DoHide( bool hide
, int flags
)
2047 ClearFlag( wxPG_PROP_HIDDEN
);
2049 SetFlag( wxPG_PROP_HIDDEN
);
2051 if ( flags
& wxPG_RECURSE
)
2054 for ( i
= 0; i
< GetChildCount(); i
++ )
2055 Item(i
)->DoHide(hide
, flags
| wxPG_RECURSE_STARTS
);
2061 bool wxPGProperty::HasVisibleChildren() const
2065 for ( i
=0; i
<GetChildCount(); i
++ )
2067 wxPGProperty
* child
= Item(i
);
2069 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
2076 bool wxPGProperty::RecreateEditor()
2078 wxPropertyGrid
* pg
= GetGrid();
2081 wxPGProperty
* selected
= pg
->GetSelection();
2082 if ( this == selected
)
2084 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
2091 void wxPGProperty::SetValueImage( wxBitmap
& bmp
)
2093 delete m_valueBitmap
;
2095 if ( &bmp
&& bmp
.IsOk() )
2098 wxSize maxSz
= GetGrid()->GetImageSize();
2099 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
2101 if ( imSz
.y
!= maxSz
.y
)
2104 // Here we use high-quality wxImage scaling functions available
2105 wxImage img
= bmp
.ConvertToImage();
2106 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
2107 img
.Rescale(wxRound(bmp
.GetWidth()*scaleY
),
2108 wxRound(bmp
.GetHeight()*scaleY
),
2109 wxIMAGE_QUALITY_HIGH
);
2110 wxBitmap
* bmpNew
= new wxBitmap(img
, 32);
2112 // This is the old, deprecated method of scaling the image
2113 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
2115 dc
.SelectObject(*bmpNew
);
2116 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
2117 dc
.SetUserScale(scaleY
, scaleY
);
2118 dc
.DrawBitmap(bmp
, 0, 0);
2121 m_valueBitmap
= bmpNew
;
2125 m_valueBitmap
= new wxBitmap(bmp
);
2128 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
2132 m_valueBitmap
= NULL
;
2133 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
2138 wxPGProperty
* wxPGProperty::GetMainParent() const
2140 const wxPGProperty
* curChild
= this;
2141 const wxPGProperty
* curParent
= m_parent
;
2143 while ( curParent
&& !curParent
->IsCategory() )
2145 curChild
= curParent
;
2146 curParent
= curParent
->m_parent
;
2149 return (wxPGProperty
*) curChild
;
2153 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const
2156 // Returns last visible sub-item, recursively.
2157 if ( !IsExpanded() || !GetChildCount() )
2160 return Last()->GetLastVisibleSubItem();
2164 bool wxPGProperty::IsVisible() const
2166 const wxPGProperty
* parent
;
2168 if ( HasFlag(wxPG_PROP_HIDDEN
) )
2171 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
2173 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
2180 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const
2182 wxPropertyGridPageState
* state
= GetParentState();
2185 wxPropertyGrid
* propGrid
= state
->GetGrid();
2186 if ( state
== propGrid
->GetState() )
2192 int wxPGProperty::GetY2( int lh
) const
2194 const wxPGProperty
* parent
;
2195 const wxPGProperty
* child
= this;
2199 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
2201 if ( !parent
->IsExpanded() )
2203 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
2208 y
-= lh
; // need to reduce one level
2214 int wxPGProperty::GetY() const
2216 return GetY2(GetGrid()->GetRowHeight());
2219 // This is used by Insert etc.
2220 void wxPGProperty::DoAddChild( wxPGProperty
* prop
, int index
,
2223 if ( index
< 0 || (size_t)index
>= m_children
.size() )
2225 if ( correct_mode
) prop
->m_arrIndex
= m_children
.size();
2226 m_children
.push_back( prop
);
2230 m_children
.insert( m_children
.begin()+index
, prop
);
2231 if ( correct_mode
) FixIndicesOfChildren( index
);
2234 prop
->m_parent
= this;
2237 void wxPGProperty::DoPreAddChild( int index
, wxPGProperty
* prop
)
2239 wxASSERT_MSG( prop
->GetBaseName().length(),
2240 "Property's children must have unique, non-empty "
2241 "names within their scope" );
2243 prop
->m_arrIndex
= index
;
2244 m_children
.insert( m_children
.begin()+index
,
2247 int custImgHeight
= prop
->OnMeasureImage().y
;
2248 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
2249 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
2251 prop
->m_parent
= this;
2254 void wxPGProperty::AddPrivateChild( wxPGProperty
* prop
)
2256 if ( !(m_flags
& wxPG_PROP_PARENTAL_FLAGS
) )
2257 SetParentalType(wxPG_PROP_AGGREGATE
);
2259 wxASSERT_MSG( (m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
2260 wxPG_PROP_AGGREGATE
,
2261 "Do not mix up AddPrivateChild() calls with other "
2262 "property adders." );
2264 DoPreAddChild( m_children
.size(), prop
);
2267 #if wxPG_COMPATIBILITY_1_4
2268 void wxPGProperty::AddChild( wxPGProperty
* prop
)
2270 AddPrivateChild(prop
);
2274 wxPGProperty
* wxPGProperty::InsertChild( int index
,
2275 wxPGProperty
* childProperty
)
2278 index
= m_children
.size();
2280 if ( m_parentState
)
2282 m_parentState
->DoInsert(this, index
, childProperty
);
2286 if ( !(m_flags
& wxPG_PROP_PARENTAL_FLAGS
) )
2287 SetParentalType(wxPG_PROP_MISC_PARENT
);
2289 wxASSERT_MSG( (m_flags
& wxPG_PROP_PARENTAL_FLAGS
) ==
2290 wxPG_PROP_MISC_PARENT
,
2291 "Do not mix up AddPrivateChild() calls with other "
2292 "property adders." );
2294 DoPreAddChild( index
, childProperty
);
2297 return childProperty
;
2300 void wxPGProperty::RemoveChild( wxPGProperty
* p
)
2302 wxArrayPGProperty::iterator it
;
2303 wxArrayPGProperty
& children
= m_children
;
2305 for ( it
=children
.begin(); it
!= children
.end(); it
++ )
2315 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
2317 wxASSERT( GetChildCount() );
2318 wxASSERT( !IsCategory() );
2320 *value
= GetValue();
2322 if ( !list
.GetCount() )
2325 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
2327 bool allChildrenSpecified
;
2329 // Don't fully update aggregate properties unless all children have
2331 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
2332 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
2334 allChildrenSpecified
= true;
2338 wxVariant childValue
= list
[n
];
2340 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
2342 for ( i
=0; i
<GetChildCount(); i
++ )
2344 const wxPGProperty
* child
= Item(i
);
2346 if ( childValue
.GetName() == child
->GetBaseName() )
2348 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
2350 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
2352 wxVariant
cv2(child
->GetValue());
2353 child
->AdaptListToValue(childValue
, &cv2
);
2357 if ( allChildrenSpecified
)
2359 *value
= ChildChanged(*value
, i
, childValue
);
2363 if ( n
== (unsigned int)list
.GetCount() )
2365 childValue
= list
[n
];
2371 void wxPGProperty::FixIndicesOfChildren( unsigned int starthere
)
2374 for ( i
=starthere
;i
<GetChildCount();i
++)
2375 Item(i
)->m_arrIndex
= i
;
2379 // Returns (direct) child property with given name (or NULL if not found)
2380 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name
) const
2384 for ( i
=0; i
<GetChildCount(); i
++ )
2386 wxPGProperty
* p
= Item(i
);
2387 if ( p
->m_name
== name
)
2391 // Does it have point, then?
2392 int pos
= name
.Find(wxS('.'));
2396 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
2398 if ( !p
|| !p
->GetChildCount() )
2401 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
2404 wxPGProperty
* wxPGProperty::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex
) const
2406 unsigned int i
= hintIndex
;
2408 if ( i
>= GetChildCount() )
2411 unsigned int lastIndex
= i
- 1;
2413 if ( lastIndex
>= GetChildCount() )
2414 lastIndex
= GetChildCount() - 1;
2418 wxPGProperty
* p
= Item(i
);
2419 if ( p
->m_name
== name
)
2422 if ( i
== lastIndex
)
2426 if ( i
== GetChildCount() )
2433 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_
) const
2435 // Returns height of children, recursively, and
2436 // by taking expanded/collapsed status into account.
2438 // iMax is used when finding property y-positions.
2444 iMax_
= GetChildCount();
2446 unsigned int iMax
= iMax_
;
2448 wxASSERT( iMax
<= GetChildCount() );
2450 if ( !IsExpanded() && GetParent() )
2455 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
2457 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
2459 if ( !pwc
->IsExpanded() ||
2460 pwc
->GetChildCount() == 0 )
2463 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
2472 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
,
2474 unsigned int* nextItemY
) const
2476 wxASSERT( nextItemY
);
2478 // Linear search at the moment
2480 // nextItemY = y of next visible property, final value will be written back.
2481 wxPGProperty
* result
= NULL
;
2482 wxPGProperty
* current
= NULL
;
2483 unsigned int iy
= *nextItemY
;
2485 unsigned int iMax
= GetChildCount();
2489 wxPGProperty
* pwc
= Item(i
);
2491 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
2502 if ( pwc
->IsExpanded() &&
2503 pwc
->GetChildCount() > 0 )
2505 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
2517 if ( !result
&& y
< iy
)
2525 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
2529 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
2533 return (wxPGProperty
*) result
;
2536 void wxPGProperty::Empty()
2539 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
2541 for ( i
=0; i
<GetChildCount(); i
++ )
2543 delete m_children
[i
];
2550 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
) const
2552 unsigned int nextItem
;
2553 return GetItemAtY( y
, GetGrid()->GetRowHeight(), &nextItem
);
2556 void wxPGProperty::DeleteChildren()
2558 wxPropertyGridPageState
* state
= m_parentState
;
2560 if ( !GetChildCount() )
2563 // Because deletion is sometimes deferred, we have to use
2564 // this sort of code for enumerating the child properties.
2565 unsigned int i
= GetChildCount();
2569 state
->DoDelete(Item(i
), true);
2573 bool wxPGProperty::IsChildSelected( bool recursive
) const
2576 for ( i
= 0; i
< GetChildCount(); i
++ )
2578 wxPGProperty
* child
= Item(i
);
2581 if ( m_parentState
->DoIsPropertySelected( child
) )
2585 if ( recursive
&& child
->IsChildSelected( recursive
) )
2592 wxVariant
wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
2593 int WXUNUSED(childIndex
),
2594 wxVariant
& WXUNUSED(childValue
) ) const
2596 return wxNullVariant
;
2599 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList
) const
2603 const wxVariantList
* pList
= NULL
;
2604 wxVariantList::const_iterator node
;
2608 pList
= &pendingList
->GetList();
2609 node
= pList
->begin();
2612 for ( i
=0; i
<GetChildCount(); i
++ )
2614 wxPGProperty
* child
= Item(i
);
2615 const wxVariant
* listValue
= NULL
;
2620 const wxString
& childName
= child
->GetBaseName();
2622 for ( ; node
!= pList
->end(); ++node
)
2624 const wxVariant
& item
= *((const wxVariant
*)*node
);
2625 if ( item
.GetName() == childName
)
2635 value
= child
->GetValue();
2637 if ( value
.IsNull() )
2640 // Check recursively
2641 if ( child
->GetChildCount() )
2643 const wxVariant
* childList
= NULL
;
2645 if ( listValue
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST
)
2646 childList
= listValue
;
2648 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
2656 wxPGProperty
* wxPGProperty::UpdateParentValues()
2658 wxPGProperty
* parent
= m_parent
;
2659 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
2660 !parent
->IsCategory() && !parent
->IsRoot() )
2663 parent
->DoGenerateComposedValue(s
);
2664 parent
->m_value
= s
;
2665 return parent
->UpdateParentValues();
2670 bool wxPGProperty::IsTextEditable() const
2672 if ( HasFlag(wxPG_PROP_READONLY
) )
2675 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
2677 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
2684 // Call after fixed sub-properties added/removed after creation.
2685 // if oldSelInd >= 0 and < new max items, then selection is
2686 // moved to it. Note: oldSelInd -2 indicates that this property
2687 // should be selected.
2688 void wxPGProperty::SubPropsChanged( int oldSelInd
)
2690 wxPropertyGridPageState
* state
= GetParentState();
2691 wxPropertyGrid
* grid
= state
->GetGrid();
2694 // Re-repare children (recursively)
2695 for ( unsigned int i
=0; i
<GetChildCount(); i
++ )
2697 wxPGProperty
* child
= Item(i
);
2698 child
->InitAfterAdded(state
, grid
);
2701 wxPGProperty
* sel
= NULL
;
2702 if ( oldSelInd
>= (int)m_children
.size() )
2703 oldSelInd
= (int)m_children
.size() - 1;
2705 if ( oldSelInd
>= 0 )
2706 sel
= m_children
[oldSelInd
];
2707 else if ( oldSelInd
== -2 )
2711 state
->DoSelectProperty(sel
);
2713 if ( state
== grid
->GetState() )
2715 grid
->GetPanel()->Refresh();
2719 // -----------------------------------------------------------------------
2721 // -----------------------------------------------------------------------
2723 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2724 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2727 wxPGRootProperty::wxPGRootProperty( const wxString
& name
)
2737 wxPGRootProperty::~wxPGRootProperty()
2742 // -----------------------------------------------------------------------
2743 // wxPropertyCategory
2744 // -----------------------------------------------------------------------
2746 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2747 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2749 void wxPropertyCategory::Init()
2751 // don't set colour - prepareadditem method should do this
2752 SetParentalType(wxPG_PROP_CATEGORY
);
2753 m_capFgColIndex
= 1;
2757 wxPropertyCategory::wxPropertyCategory()
2764 wxPropertyCategory::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2765 : wxPGProperty(label
,name
)
2771 wxPropertyCategory::~wxPropertyCategory()
2776 wxString
wxPropertyCategory::ValueToString( wxVariant
& WXUNUSED(value
),
2777 int WXUNUSED(argFlags
) ) const
2779 if ( m_value
.GetType() == wxPG_VARIANT_TYPE_STRING
)
2780 return m_value
.GetString();
2781 return wxEmptyString
;
2784 wxString
wxPropertyCategory::GetValueAsString( int argFlags
) const
2786 #if wxPG_COMPATIBILITY_1_4
2787 // This is backwards compatibility test
2788 // That is, to make sure this function is not overridden
2789 // (instead, ValueToString() should be).
2790 if ( argFlags
== 0xFFFF )
2792 // Do not override! (for backwards compliancy)
2793 return g_invalidStringContent
;
2797 // Unspecified value is always empty string
2798 if ( IsValueUnspecified() )
2799 return wxEmptyString
;
2801 return wxPGProperty::GetValueAsString(argFlags
);
2804 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2806 if ( m_textExtent
> 0 )
2807 return m_textExtent
;
2809 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2813 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2816 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2820 // -----------------------------------------------------------------------
2822 // -----------------------------------------------------------------------
2824 wxPGChoiceEntry
& wxPGChoices::Add( const wxString
& label
, int value
)
2828 wxPGChoiceEntry
entry(label
, value
);
2829 return m_data
->Insert( -1, entry
);
2832 // -----------------------------------------------------------------------
2834 wxPGChoiceEntry
& wxPGChoices::Add( const wxString
& label
, const wxBitmap
& bitmap
, int value
)
2838 wxPGChoiceEntry
entry(label
, value
);
2839 entry
.SetBitmap(bitmap
);
2840 return m_data
->Insert( -1, entry
);
2843 // -----------------------------------------------------------------------
2845 wxPGChoiceEntry
& wxPGChoices::Insert( const wxPGChoiceEntry
& entry
, int index
)
2849 return m_data
->Insert( index
, entry
);
2852 // -----------------------------------------------------------------------
2854 wxPGChoiceEntry
& wxPGChoices::Insert( const wxString
& label
, int index
, int value
)
2858 wxPGChoiceEntry
entry(label
, value
);
2859 return m_data
->Insert( index
, entry
);
2862 // -----------------------------------------------------------------------
2864 wxPGChoiceEntry
& wxPGChoices::AddAsSorted( const wxString
& label
, int value
)
2870 while ( index
< GetCount() )
2872 int cmpRes
= GetLabel(index
).Cmp(label
);
2878 wxPGChoiceEntry
entry(label
, value
);
2879 return m_data
->Insert( index
, entry
);
2882 // -----------------------------------------------------------------------
2884 void wxPGChoices::Add( const wxChar
* const* labels
, const ValArrItem
* values
)
2888 unsigned int itemcount
= 0;
2889 const wxChar
* const* p
= &labels
[0];
2890 while ( *p
) { p
++; itemcount
++; }
2893 for ( i
= 0; i
< itemcount
; i
++ )
2898 wxPGChoiceEntry
entry(labels
[i
], value
);
2899 m_data
->Insert( i
, entry
);
2903 // -----------------------------------------------------------------------
2905 void wxPGChoices::Add( const wxArrayString
& arr
, const wxArrayInt
& arrint
)
2910 unsigned int itemcount
= arr
.size();
2912 for ( i
= 0; i
< itemcount
; i
++ )
2915 if ( &arrint
&& arrint
.size() )
2917 wxPGChoiceEntry
entry(arr
[i
], value
);
2918 m_data
->Insert( i
, entry
);
2922 // -----------------------------------------------------------------------
2924 void wxPGChoices::RemoveAt(size_t nIndex
, size_t count
)
2928 wxASSERT( m_data
->GetRefCount() != -1 );
2929 m_data
->m_items
.erase(m_data
->m_items
.begin()+nIndex
,
2930 m_data
->m_items
.begin()+nIndex
+count
);
2933 // -----------------------------------------------------------------------
2935 void wxPGChoices::Clear()
2937 if ( m_data
!= wxPGChoicesEmptyData
)
2944 // -----------------------------------------------------------------------
2946 int wxPGChoices::Index( const wxString
& str
) const
2951 for ( i
=0; i
< m_data
->GetCount(); i
++ )
2953 const wxPGChoiceEntry
& entry
= m_data
->Item(i
);
2954 if ( entry
.HasText() && entry
.GetText() == str
)
2961 // -----------------------------------------------------------------------
2963 int wxPGChoices::Index( int val
) const
2968 for ( i
=0; i
< m_data
->GetCount(); i
++ )
2970 const wxPGChoiceEntry
& entry
= m_data
->Item(i
);
2971 if ( entry
.GetValue() == val
)
2978 // -----------------------------------------------------------------------
2980 wxArrayString
wxPGChoices::GetLabels() const
2985 if ( this && IsOk() )
2986 for ( i
=0; i
<GetCount(); i
++ )
2987 arr
.push_back(GetLabel(i
));
2992 // -----------------------------------------------------------------------
2994 wxArrayInt
wxPGChoices::GetValuesForStrings( const wxArrayString
& strings
) const
3001 for ( i
=0; i
< strings
.size(); i
++ )
3003 int index
= Index(strings
[i
]);
3005 arr
.Add(GetValue(index
));
3007 arr
.Add(wxPG_INVALID_VALUE
);
3014 // -----------------------------------------------------------------------
3016 wxArrayInt
wxPGChoices::GetIndicesForStrings( const wxArrayString
& strings
,
3017 wxArrayString
* unmatched
) const
3024 for ( i
=0; i
< strings
.size(); i
++ )
3026 const wxString
& str
= strings
[i
];
3027 int index
= Index(str
);
3030 else if ( unmatched
)
3031 unmatched
->Add(str
);
3038 // -----------------------------------------------------------------------
3040 void wxPGChoices::AllocExclusive()
3044 if ( m_data
->GetRefCount() != 1 )
3046 wxPGChoicesData
* data
= new wxPGChoicesData();
3047 data
->CopyDataFrom(m_data
);
3053 // -----------------------------------------------------------------------
3055 void wxPGChoices::AssignData( wxPGChoicesData
* data
)
3059 if ( data
!= wxPGChoicesEmptyData
)
3066 // -----------------------------------------------------------------------
3068 void wxPGChoices::Init()
3070 m_data
= wxPGChoicesEmptyData
;
3073 // -----------------------------------------------------------------------
3075 void wxPGChoices::Free()
3077 if ( m_data
!= wxPGChoicesEmptyData
)
3080 m_data
= wxPGChoicesEmptyData
;
3084 // -----------------------------------------------------------------------
3085 // wxPGAttributeStorage
3086 // -----------------------------------------------------------------------
3088 wxPGAttributeStorage::wxPGAttributeStorage()
3092 wxPGAttributeStorage::~wxPGAttributeStorage()
3094 wxPGHashMapS2P::iterator it
;
3096 for ( it
= m_map
.begin(); it
!= m_map
.end(); ++it
)
3098 wxVariantData
* data
= (wxVariantData
*) it
->second
;
3103 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value
)
3105 wxVariantData
* data
= value
.GetData();
3108 wxPGHashMapS2P::iterator it
= m_map
.find(name
);
3109 if ( it
!= m_map
.end() )
3111 ((wxVariantData
*)it
->second
)->DecRef();
3115 // If Null variant, just remove from set
3129 #endif // wxUSE_PROPGRID