1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/propgrid/property.cpp 
   3 // Purpose:     wxPGProperty and related support classes 
   4 // Author:      Jaakko Salli 
   8 // Copyright:   (c) Jaakko Salli 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx/wx.h". 
  13 #include "wx/wxprec.h" 
  23     #include "wx/object.h" 
  25     #include "wx/string.h" 
  28     #include "wx/window.h" 
  31     #include "wx/dcmemory.h" 
  34     #include "wx/settings.h" 
  38 #include "wx/propgrid/propgrid.h" 
  41 #define PWC_CHILD_SUMMARY_LIMIT         16 // Maximum number of children summarized in a parent property's 
  44 #define PWC_CHILD_SUMMARY_CHAR_LIMIT    64 // Character limit of summary field when not editing 
  46 #if wxPG_COMPATIBILITY_1_4 
  48 // Used to establish backwards compatiblity 
  49 const char* g_invalidStringContent 
= "@__TOTALLY_INVALID_STRING__@"; 
  53 // ----------------------------------------------------------------------- 
  55 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect 
) 
  57 #if defined(__WXMSW__) && !defined(__WXWINCE__) 
  58     // FIXME: Use DrawFocusRect code above (currently it draws solid line 
  59     //   for caption focus but works ok for other stuff). 
  60     //   Also, it seems that this code may not work in future wx versions. 
  61     dc
.SetLogicalFunction(wxINVERT
); 
  63     wxPen 
pen(*wxBLACK
,1,wxDOT
); 
  64     pen
.SetCap(wxCAP_BUTT
); 
  66     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
  68     dc
.DrawRectangle(rect
); 
  70     dc
.SetLogicalFunction(wxCOPY
); 
  72     dc
.SetLogicalFunction(wxINVERT
); 
  74     dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
)); 
  75     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
  77     dc
.DrawRectangle(rect
); 
  79     dc
.SetLogicalFunction(wxCOPY
); 
  83 // ----------------------------------------------------------------------- 
  85 // ----------------------------------------------------------------------- 
  87 wxSize 
wxPGCellRenderer::GetImageSize( const wxPGProperty
* WXUNUSED(property
), 
  89                                        int WXUNUSED(item
) ) const 
  94 void wxPGCellRenderer::DrawText( wxDC
& dc
, const wxRect
& rect
, 
  95                                  int xOffset
, const wxString
& text 
) const 
  98                  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         dc
.SetPen(cell
.GetBgCol()); 
 139         dc
.SetBrush(cell
.GetBgCol()); 
 142     if ( !(flags 
& DontUseCellFgCol
) ) 
 144         dc
.SetTextForeground(cell
.GetFgCol()); 
 147     // Draw Background, but only if not rendering in control 
 148     // (as control already has rendered correct background). 
 149     if ( !(flags 
& (Control
|ChoicePopup
)) ) 
 150         dc
.DrawRectangle(rect
); 
 152     const wxBitmap
& bmp 
= cell
.GetBitmap(); 
 154         // Do not draw oversized bitmap outside choice popup 
 155          ((flags 
& ChoicePopup
) || bmp
.GetHeight() < rect
.height 
) 
 159                        rect
.x 
+ wxPG_CONTROL_MARGIN 
+ wxCC_CUSTOM_IMAGE_MARGIN1
, 
 160                        rect
.y 
+ wxPG_CUSTOM_IMAGE_SPACINGY
, 
 162         imageWidth 
= bmp
.GetWidth(); 
 168 // ----------------------------------------------------------------------- 
 169 // wxPGDefaultRenderer 
 170 // ----------------------------------------------------------------------- 
 172 void wxPGDefaultRenderer::Render( wxDC
& dc
, const wxRect
& rect
, 
 173                                   const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
, 
 174                                   int column
, int item
, int flags 
) const 
 176     bool isUnspecified 
= property
->IsValueUnspecified(); 
 178     if ( column 
== 1 && item 
== -1 ) 
 180         int cmnVal 
= property
->GetCommonValue(); 
 184             if ( !isUnspecified 
) 
 185                 DrawText( dc
, rect
, 0, propertyGrid
->GetCommonValueLabel(cmnVal
) ); 
 190     const wxPGEditor
* editor 
= NULL
; 
 191     const wxPGCell
* cell 
= NULL
; 
 195     int preDrawFlags 
= flags
; 
 197     property
->GetDisplayInfo(column
, item
, flags
, &text
, &cell
); 
 199     imageWidth 
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags 
); 
 203         if ( !isUnspecified 
) 
 205             editor 
= property
->GetColumnEditor(column
); 
 207             // Regular property value 
 209             wxSize imageSize 
= propertyGrid
->GetImageSize(property
, item
); 
 211             wxPGPaintData paintdata
; 
 212             paintdata
.m_parent 
= propertyGrid
; 
 213             paintdata
.m_choiceItem 
= item
; 
 215             if ( imageSize
.x 
> 0 ) 
 217                 wxRect 
imageRect(rect
.x 
+ wxPG_CONTROL_MARGIN 
+ wxCC_CUSTOM_IMAGE_MARGIN1
, 
 218                                  rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
, 
 219                                  wxPG_CUSTOM_IMAGE_WIDTH
, 
 220                                  rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2)); 
 222                 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) ); 
 224                 paintdata
.m_drawnWidth 
= imageSize
.x
; 
 225                 paintdata
.m_drawnHeight 
= imageSize
.y
; 
 227                 property
->OnCustomPaint( dc
, imageRect
, paintdata 
); 
 229                 imageWidth 
= paintdata
.m_drawnWidth
; 
 232             text 
= property
->GetValueAsString(); 
 235             if ( propertyGrid
->GetColumnCount() <= 2 ) 
 237                 wxString unitsString 
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
); 
 238                 if ( unitsString
.length() ) 
 239                     text 
= wxString::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() ); 
 243         if ( text
.length() == 0 ) 
 245             // Try to show inline help if no text 
 246             wxVariant vInlineHelp 
= property
->GetAttribute(wxPGGlobalVars
->m_strInlineHelp
); 
 247             if ( !vInlineHelp
.IsNull() ) 
 249                 text 
= vInlineHelp
.GetString(); 
 250                 dc
.SetTextForeground(propertyGrid
->GetCellDisabledTextColour()); 
 255     int imageOffset 
= property
->GetImageOffset(imageWidth
); 
 257     DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor 
); 
 259     // active caption gets nice dotted rectangle 
 260     if ( property
->IsCategory() /*&& column == 0*/ ) 
 262         if ( flags 
& Selected 
) 
 264             if ( imageWidth 
> 0 ) 
 266                 imageOffset 
-= DEFAULT_IMAGE_OFFSET_INCREMENT
; 
 267                 imageWidth 
+= wxCC_CUSTOM_IMAGE_MARGIN2 
+ 4; 
 270             DrawCaptionSelectionRect( dc
, 
 271                                       rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
, 
 272                                       rect
.y
-wxPG_CAPRECTYMARGIN
+1, 
 273                                       ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
, 
 274                                                                                      propertyGrid
->GetCaptionFont()) 
 275                                       +(wxPG_CAPRECTXMARGIN
*2), 
 276                                       propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) ); 
 281 wxSize 
wxPGDefaultRenderer::GetImageSize( const wxPGProperty
* property
, 
 285     if ( property 
&& column 
== 1 ) 
 289             wxBitmap
* bmp 
= property
->GetValueImage(); 
 291             if ( bmp 
&& bmp
->Ok() ) 
 292                 return wxSize(bmp
->GetWidth(),bmp
->GetHeight()); 
 298 // ----------------------------------------------------------------------- 
 300 // ----------------------------------------------------------------------- 
 302 wxPGCellData::wxPGCellData() 
 305     m_hasValidText 
= false; 
 308 // ----------------------------------------------------------------------- 
 310 // ----------------------------------------------------------------------- 
 317 wxPGCell::wxPGCell( const wxString
& text
, 
 318                     const wxBitmap
& bitmap
, 
 319                     const wxColour
& fgCol
, 
 320                     const wxColour
& bgCol 
) 
 323     wxPGCellData
* data 
= new wxPGCellData(); 
 326     data
->m_bitmap 
= bitmap
; 
 327     data
->m_fgCol 
= fgCol
; 
 328     data
->m_bgCol 
= bgCol
; 
 329     data
->m_hasValidText 
= true; 
 332 wxObjectRefData 
*wxPGCell::CloneRefData( const wxObjectRefData 
*data 
) const 
 334     wxPGCellData
* c 
= new wxPGCellData(); 
 335     const wxPGCellData
* o 
= (const wxPGCellData
*) data
; 
 336     c
->m_text 
= o
->m_text
; 
 337     c
->m_bitmap 
= o
->m_bitmap
; 
 338     c
->m_fgCol 
= o
->m_fgCol
; 
 339     c
->m_bgCol 
= o
->m_bgCol
; 
 340     c
->m_hasValidText 
= o
->m_hasValidText
; 
 344 void wxPGCell::SetText( const wxString
& text 
) 
 348     GetData()->SetText(text
); 
 351 void wxPGCell::SetBitmap( const wxBitmap
& bitmap 
) 
 355     GetData()->SetBitmap(bitmap
); 
 358 void wxPGCell::SetFgCol( const wxColour
& col 
) 
 362     GetData()->SetFgCol(col
); 
 365 void wxPGCell::SetBgCol( const wxColour
& col 
) 
 369     GetData()->SetBgCol(col
); 
 372 void wxPGCell::MergeFrom( const wxPGCell
& srcCell 
) 
 376     wxPGCellData
* data 
= GetData(); 
 378     if ( srcCell
.HasText() ) 
 379         data
->SetText(srcCell
.GetText()); 
 381     if ( srcCell
.GetFgCol().IsOk() ) 
 382         data
->SetFgCol(srcCell
.GetFgCol()); 
 384     if ( srcCell
.GetBgCol().IsOk() ) 
 385         data
->SetBgCol(srcCell
.GetBgCol()); 
 387     if ( srcCell
.GetBitmap().IsOk() ) 
 388         data
->SetBitmap(srcCell
.GetBitmap()); 
 391 // ----------------------------------------------------------------------- 
 393 // ----------------------------------------------------------------------- 
 395 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
) 
 397 wxString
* wxPGProperty::sm_wxPG_LABEL 
= NULL
; 
 399 void wxPGProperty::Init() 
 405     m_parentState 
= NULL
; 
 408     m_clientObject 
= NULL
; 
 410     m_customEditor 
= NULL
; 
 414     m_valueBitmap 
= NULL
; 
 416     m_maxLen 
= 0; // infinite maximum length 
 418     m_flags 
= wxPG_PROP_PROPERTY
; 
 426 void wxPGProperty::Init( const wxString
& label
, const wxString
& name 
) 
 428     // We really need to check if &label and &name are NULL pointers 
 429     // (this can if we are called before property grid has been initalized) 
 431     if ( (&label
) != NULL 
&& label 
!= wxPG_LABEL 
) 
 434     if ( (&name
) != NULL 
&& name 
!= wxPG_LABEL 
) 
 437         DoSetName( m_label 
); 
 442 void wxPGProperty::InitAfterAdded( wxPropertyGridPageState
* pageState
, 
 443                                    wxPropertyGrid
* propgrid 
) 
 446     // Called after property has been added to grid or page 
 447     // (so propgrid can be NULL, too). 
 449     wxPGProperty
* parent 
= m_parent
; 
 450     bool parentIsRoot 
= parent
->IsKindOf(CLASSINFO(wxPGRootProperty
)); 
 452     m_parentState 
= pageState
; 
 454 #if wxPG_COMPATIBILITY_1_4 
 455     // Make sure deprecated virtual functions are not implemented 
 456     wxString s 
= GetValueAsString( 0xFFFF ); 
 457     wxASSERT_MSG( s 
== g_invalidStringContent
, 
 458                   "Implement ValueToString() instead of GetValueAsString()" ); 
 461     if ( !parentIsRoot 
&& !parent
->IsCategory() ) 
 463         m_cells 
= parent
->m_cells
; 
 466     // If in hideable adding mode, or if assigned parent is hideable, then 
 467     // make this one hideable. 
 469          ( !parentIsRoot 
&& parent
->HasFlag(wxPG_PROP_HIDDEN
) ) || 
 470          ( propgrid 
&& (propgrid
->HasInternalFlag(wxPG_FL_ADDING_HIDEABLES
)) ) 
 472         SetFlag( wxPG_PROP_HIDDEN 
); 
 474     // Set custom image flag. 
 475     int custImgHeight 
= OnMeasureImage().y
; 
 476     if ( custImgHeight 
< 0 ) 
 478         SetFlag(wxPG_PROP_CUSTOMIMAGE
); 
 481     if ( propgrid 
&& (propgrid
->HasFlag(wxPG_LIMITED_EDITING
)) ) 
 482         SetFlag(wxPG_PROP_NOEDITOR
); 
 484     // Make sure parent has some parental flags 
 485     if ( !parent
->HasFlag(wxPG_PROP_PARENTAL_FLAGS
) ) 
 486         parent
->SetParentalType(wxPG_PROP_MISC_PARENT
); 
 490         // This is not a category. 
 494         unsigned char depth 
= 1; 
 497             depth 
= parent
->m_depth
; 
 498             if ( !parent
->IsCategory() ) 
 502         unsigned char greyDepth 
= depth
; 
 506             wxPropertyCategory
* pc
; 
 508             if ( parent
->IsCategory() ) 
 509                 pc 
= (wxPropertyCategory
* ) parent
; 
 511                 // This conditional compile is necessary to 
 512                 // bypass some compiler bug. 
 513                 pc 
= pageState
->GetPropertyCategory(parent
); 
 516                 greyDepth 
= pc
->GetDepth(); 
 518                 greyDepth 
= parent
->m_depthBgCol
; 
 521         m_depthBgCol 
= greyDepth
; 
 525         // This is a category. 
 528         unsigned char depth 
= 1; 
 531             depth 
= parent
->m_depth 
+ 1; 
 534         m_depthBgCol 
= depth
; 
 538     // Has initial children 
 539     if ( GetChildCount() ) 
 541         // Check parental flags 
 542         wxASSERT_MSG( (m_flags 
& wxPG_PROP_PARENTAL_FLAGS
), 
 543                       "Call SetFlag(wxPG_PROP_MISC_PARENT) or" 
 544                       "SetFlag(wxPG_PROP_AGGREGATE) before calling" 
 545                       "wxPGProperty::AddChild()." ); 
 547         if ( HasFlag(wxPG_PROP_AGGREGATE
) ) 
 549             // Properties with private children are not expanded by default. 
 552         else if ( propgrid 
&& propgrid
->HasFlag(wxPG_HIDE_MARGIN
) ) 
 554             // ...unless it cannot be expanded by user and therefore must 
 555             // remain visible at all times 
 560         // Prepare children recursively 
 561         for ( unsigned int i
=0; i
<GetChildCount(); i
++ ) 
 563             wxPGProperty
* child 
= Item(i
); 
 564             child
->InitAfterAdded(pageState
, pageState
->GetGrid()); 
 567         if ( propgrid 
&& (propgrid
->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES
) ) 
 568             SetFlagRecursively(wxPG_PROP_AUTO_UNSPECIFIED
, true); 
 572 wxPGProperty::wxPGProperty() 
 579 wxPGProperty::wxPGProperty( const wxString
& label
, const wxString
& name 
) 
 586 wxPGProperty::~wxPGProperty() 
 588     delete m_clientObject
; 
 590     Empty();  // this deletes items 
 592     delete m_valueBitmap
; 
 597     // This makes it easier for us to detect dangling pointers 
 602 bool wxPGProperty::IsSomeParent( wxPGProperty
* candidate 
) const 
 604     wxPGProperty
* parent 
= m_parent
; 
 607         if ( parent 
== candidate 
) 
 609         parent 
= parent
->m_parent
; 
 615 wxString 
wxPGProperty::GetName() const 
 617     wxPGProperty
* parent 
= GetParent(); 
 619     if ( !m_name
.length() || !parent 
|| parent
->IsCategory() || parent
->IsRoot() ) 
 622     return m_parent
->GetName() + wxS(".") + m_name
; 
 625 wxPropertyGrid
* wxPGProperty::GetGrid() const 
 627     if ( !m_parentState 
) 
 629     return m_parentState
->GetGrid(); 
 632 int wxPGProperty::Index( const wxPGProperty
* p 
) const 
 634     for ( unsigned int i 
= 0; i
<m_children
.size(); i
++ ) 
 636         if ( p 
== m_children
[i
] ) 
 642 bool wxPGProperty::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const 
 647 void wxPGProperty::OnSetValue() 
 651 void wxPGProperty::RefreshChildren () 
 655 void wxPGProperty::OnValidationFailure( wxVariant
& WXUNUSED(pendingValue
) ) 
 659 void wxPGProperty::GetDisplayInfo( unsigned int column
, 
 663                                    const wxPGCell
** pCell 
) 
 665     const wxPGCell
* cell 
= NULL
; 
 667     if ( !(flags 
& wxPGCellRenderer::ChoicePopup
) ) 
 669         // Not painting listi of choice popups, so get text from property 
 670         cell 
= &GetCell(column
); 
 671         if ( cell
->HasText() ) 
 673             *pString 
= cell
->GetText(); 
 678                 *pString 
= GetLabel(); 
 679             else if ( column 
== 1 ) 
 680                 *pString 
= GetDisplayedString(); 
 681             else if ( column 
== 2 ) 
 682                 *pString 
= GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
); 
 687         wxASSERT( column 
== 1 ); 
 689         if ( choiceIndex 
!= wxNOT_FOUND 
) 
 691             const wxPGChoiceEntry
& entry 
= m_choices
[choiceIndex
]; 
 692             if ( entry
.GetBitmap().IsOk() || 
 693                  entry
.GetFgCol().IsOk() || 
 694                  entry
.GetBgCol().IsOk() ) 
 696             *pString 
= m_choices
.GetLabel(choiceIndex
); 
 701         cell 
= &GetCell(column
); 
 703     wxASSERT_MSG( cell
->GetData(), 
 704                   wxString::Format("Invalid cell for property %s", 
 705                                    GetName().c_str()) ); 
 711 wxString wxPGProperty::GetColumnText( unsigned int col, int choiceIndex ) const 
 714     if ( col != 1 || choiceIndex == wxNOT_FOUND ) 
 716         const wxPGCell& cell = GetCell(col); 
 717         if ( cell->HasText() ) 
 719             return cell->GetText(); 
 726                 return GetDisplayedString(); 
 728                 return GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString); 
 734         return m_choices.GetLabel(choiceIndex); 
 737     return wxEmptyString; 
 741 void wxPGProperty::DoGenerateComposedValue( wxString
& text
, 
 743                                             const wxVariantList
* valueOverrides
, 
 744                                             wxPGHashMapS2S
* childResults 
) const 
 747     int iMax 
= m_children
.size(); 
 753     if ( iMax 
> PWC_CHILD_SUMMARY_LIMIT 
&& 
 754          !(argFlags 
& wxPG_FULL_VALUE
) ) 
 755         iMax 
= PWC_CHILD_SUMMARY_LIMIT
; 
 757     int iMaxMinusOne 
= iMax
-1; 
 759     if ( !IsTextEditable() ) 
 760         argFlags 
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
; 
 762     wxPGProperty
* curChild 
= m_children
[0]; 
 764     bool overridesLeft 
= false; 
 765     wxVariant overrideValue
; 
 766     wxVariantList::const_iterator node
; 
 768     if ( valueOverrides 
) 
 770         node 
= valueOverrides
->begin(); 
 771         if ( node 
!= valueOverrides
->end() ) 
 773             overrideValue 
= *node
; 
 774             overridesLeft 
= true; 
 778     for ( i 
= 0; i 
< iMax
; i
++ ) 
 780         wxVariant childValue
; 
 782         wxString childLabel 
= curChild
->GetLabel(); 
 784         // Check for value override 
 785         if ( overridesLeft 
&& overrideValue
.GetName() == childLabel 
) 
 787             if ( !overrideValue
.IsNull() ) 
 788                 childValue 
= overrideValue
; 
 790                 childValue 
= curChild
->GetValue(); 
 792             if ( node 
!= valueOverrides
->end() ) 
 793                 overrideValue 
= *node
; 
 795                 overridesLeft 
= false; 
 799             childValue 
= curChild
->GetValue(); 
 803         if ( !childValue
.IsNull() ) 
 805             if ( overridesLeft 
&& 
 806                  curChild
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) && 
 807                  childValue
.GetType() == wxPG_VARIANT_TYPE_LIST 
) 
 809                 wxVariantList
& childList 
= childValue
.GetList(); 
 810                 DoGenerateComposedValue(s
, argFlags
|wxPG_COMPOSITE_FRAGMENT
, 
 811                                         &childList
, childResults
); 
 815                 s 
= curChild
->ValueToString(childValue
, 
 816                                             argFlags
|wxPG_COMPOSITE_FRAGMENT
); 
 820         if ( childResults 
&& curChild
->GetChildCount() ) 
 821             (*childResults
)[curChild
->GetName()] = s
; 
 824         if ( (argFlags 
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() ) 
 827         if ( !curChild
->GetChildCount() || skip 
) 
 830             text 
+= wxS("[") + s 
+ wxS("]"); 
 832         if ( i 
< iMaxMinusOne 
) 
 834             if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT 
&& 
 835                  !(argFlags 
& wxPG_EDITABLE_VALUE
) && 
 836                  !(argFlags 
& wxPG_FULL_VALUE
) ) 
 841                 if ( !curChild
->GetChildCount() ) 
 847             curChild 
= m_children
[i
+1]; 
 851     if ( (unsigned int)i 
< m_children
.size() ) 
 853         if ( !text
.EndsWith(wxS("; ")) ) 
 854             text 
+= wxS("; ..."); 
 860 wxString 
wxPGProperty::ValueToString( wxVariant
& WXUNUSED(value
), 
 863     wxCHECK_MSG( GetChildCount() > 0, 
 865                  "If user property does not have any children, it must " 
 866                  "override GetValueAsString" ); 
 868     // FIXME: Currently code below only works if value is actually m_value 
 869     wxASSERT_MSG( argFlags 
& wxPG_VALUE_IS_CURRENT
, 
 870                   "Sorry, currently default wxPGProperty::ValueToString() " 
 871                   "implementation only works if value is m_value." ); 
 874     DoGenerateComposedValue(text
, argFlags
); 
 878 wxString 
wxPGProperty::GetValueAsString( int argFlags 
) const 
 880 #if wxPG_COMPATIBILITY_1_4 
 881     // This is backwards compatibility test 
 882     // That is, to make sure this function is not overridden 
 883     // (instead, ValueToString() should be). 
 884     if ( argFlags 
== 0xFFFF ) 
 886         // Do not override! (for backwards compliancy) 
 887         return g_invalidStringContent
; 
 891     if ( IsValueUnspecified() ) 
 892         return wxEmptyString
; 
 894     if ( m_commonValue 
== -1 ) 
 896         wxVariant 
value(GetValue()); 
 897         return ValueToString(value
, argFlags
|wxPG_VALUE_IS_CURRENT
); 
 901     // Return common value's string representation 
 902     wxPropertyGrid
* pg 
= GetGrid(); 
 903     const wxPGCommonValue
* cv 
= pg
->GetCommonValue(m_commonValue
); 
 905     if ( argFlags 
& wxPG_FULL_VALUE 
) 
 907         return cv
->GetLabel(); 
 909     else if ( argFlags 
& wxPG_EDITABLE_VALUE 
) 
 911         return cv
->GetEditableText(); 
 915         return cv
->GetLabel(); 
 919 wxString 
wxPGProperty::GetValueString( int argFlags 
) const 
 921     return GetValueAsString(argFlags
); 
 924 bool wxPGProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const 
 926     variant 
= (long)number
; 
 930 // Convert semicolon delimited tokens into child values. 
 931 bool wxPGProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags 
) const 
 933     if ( !GetChildCount() ) 
 936     unsigned int curChild 
= 0; 
 938     unsigned int iMax 
= m_children
.size(); 
 940     if ( iMax 
> PWC_CHILD_SUMMARY_LIMIT 
&& 
 941          !(argFlags 
& wxPG_FULL_VALUE
) ) 
 942         iMax 
= PWC_CHILD_SUMMARY_LIMIT
; 
 944     bool changed 
= false; 
 949     // Its best only to add non-empty group items 
 950     bool addOnlyIfNotEmpty 
= false; 
 951     const wxChar delimeter 
= wxS(';'); 
 953     size_t tokenStart 
= 0xFFFFFF; 
 955     wxVariantList temp_list
; 
 956     wxVariant 
list(temp_list
); 
 958     int propagatedFlags 
= argFlags 
& (wxPG_REPORT_ERROR
|wxPG_PROGRAMMATIC_VALUE
); 
 961     bool debug_print 
= false; 
 966         wxLogDebug(wxT(">> %s.StringToValue('%s')"),GetLabel().c_str(),text
.c_str()); 
 969     wxString::const_iterator it 
= text
.begin(); 
 972     if ( it 
!= text
.end() ) 
 979         // How many units we iterate string forward at the end of loop? 
 980         // We need to keep track of this or risk going to negative 
 981         // with it-- operation. 
 982         unsigned int strPosIncrement 
= 1; 
 984         if ( tokenStart 
!= 0xFFFFFF ) 
 987             if ( a 
== delimeter 
|| a 
== 0 ) 
 989                 token 
= text
.substr(tokenStart
,pos
-tokenStart
); 
 991                 size_t len 
= token
.length(); 
 993                 if ( !addOnlyIfNotEmpty 
|| len 
> 0 ) 
 995                     const wxPGProperty
* child 
= Item(curChild
); 
 996                     wxVariant 
variant(child
->GetValue()); 
 997                     wxString childName 
= child
->GetBaseName(); 
1001                         wxLogDebug(wxT("token = '%s', child = %s"), 
1002                                    token
.c_str(), childName
.c_str()); 
1005                     // Add only if editable or setting programmatically 
1006                     if ( (argFlags 
& wxPG_PROGRAMMATIC_VALUE
) || 
1007                          !child
->HasFlag(wxPG_PROP_DISABLED
|wxPG_PROP_READONLY
) ) 
1011                             if ( child
->StringToValue(variant
, token
, 
1012                                  propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) ) 
1014                                 // We really need to set the variant's name 
1015                                 // *after* child->StringToValue() has been 
1016                                 // called, since variant's value may be set by 
1017                                 // assigning another variant into it, which 
1018                                 // then usually causes name to be copied (ie. 
1019                                 // usually cleared) as well. wxBoolProperty 
1020                                 // being case in point with its use of 
1021                                 // wxPGVariant_Bool macro as an optimization. 
1022                                 variant
.SetName(childName
); 
1023                                 list
.Append(variant
); 
1030                             // Empty, becomes unspecified 
1032                             variant
.SetName(childName
); 
1033                             list
.Append(variant
); 
1039                     if ( curChild 
>= iMax 
) 
1043                 tokenStart 
= 0xFFFFFF; 
1048             // Token is not running 
1049             if ( a 
!= wxS(' ') ) 
1052                 addOnlyIfNotEmpty 
= false; 
1054                 // Is this a group of tokens? 
1055                 if ( a 
== wxS('[') ) 
1059                     if ( it 
!= text
.end() ) ++it
; 
1061                     size_t startPos 
= pos
; 
1063                     // Group item - find end 
1064                     while ( it 
!= text
.end() && depth 
> 0 ) 
1070                         if ( a 
== wxS(']') ) 
1072                         else if ( a 
== wxS('[') ) 
1076                     token 
= text
.substr(startPos
,pos
-startPos
-1); 
1078                     if ( !token
.length() ) 
1081                     const wxPGProperty
* child 
= Item(curChild
); 
1083                     wxVariant oldChildValue 
= child
->GetValue(); 
1084                     wxVariant 
variant(oldChildValue
); 
1086                     if ( (argFlags 
& wxPG_PROGRAMMATIC_VALUE
) || 
1087                          !child
->HasFlag(wxPG_PROP_DISABLED
|wxPG_PROP_READONLY
) ) 
1089                         wxString childName 
= child
->GetBaseName(); 
1091                         bool stvRes 
= child
->StringToValue( variant
, token
, 
1093                         if ( stvRes 
|| (variant 
!= oldChildValue
) ) 
1095                             variant
.SetName(childName
); 
1096                             list
.Append(variant
); 
1107                     if ( curChild 
>= iMax 
) 
1110                     addOnlyIfNotEmpty 
= true; 
1112                     tokenStart 
= 0xFFFFFF; 
1118                     if ( a 
== delimeter 
) 
1119                         strPosIncrement 
-= 1; 
1127         it 
+= strPosIncrement
; 
1129         if ( it 
!= text
.end() ) 
1138         pos 
+= strPosIncrement
; 
1147 bool wxPGProperty::SetValueFromString( const wxString
& text
, int argFlags 
) 
1149     wxVariant 
variant(m_value
); 
1150     bool res 
= StringToValue(variant
, text
, argFlags
); 
1156 bool wxPGProperty::SetValueFromInt( long number
, int argFlags 
) 
1158     wxVariant 
variant(m_value
); 
1159     bool res 
= IntToValue(variant
, number
, argFlags
); 
1165 wxSize 
wxPGProperty::OnMeasureImage( int WXUNUSED(item
) ) const 
1167     if ( m_valueBitmap 
) 
1168         return wxSize(m_valueBitmap
->GetWidth(),-1); 
1173 int wxPGProperty::GetImageOffset( int imageWidth 
) const 
1175     int imageOffset 
= 0; 
1179         // Do not increment offset too much for wide images 
1180         if ( imageWidth 
<= (wxPG_CUSTOM_IMAGE_WIDTH
+5) ) 
1181             imageOffset 
= imageWidth 
+ DEFAULT_IMAGE_OFFSET_INCREMENT
; 
1183             imageOffset 
= imageWidth 
+ 1; 
1189 wxPGCellRenderer
* wxPGProperty::GetCellRenderer( int WXUNUSED(column
) ) const 
1191     return wxPGGlobalVars
->m_defaultRenderer
; 
1194 void wxPGProperty::OnCustomPaint( wxDC
& dc
, 
1198     wxBitmap
* bmp 
= m_valueBitmap
; 
1200     wxCHECK_RET( bmp 
&& bmp
->Ok(), wxT("invalid bitmap") ); 
1202     wxCHECK_RET( rect
.x 
>= 0, wxT("unexpected measure call") ); 
1204     dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
); 
1207 const wxPGEditor
* wxPGProperty::DoGetEditorClass() const 
1209     return wxPGEditor_TextCtrl
; 
1212 // Default extra property event handling - that is, none at all. 
1213 bool wxPGProperty::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& ) 
1219 void wxPGProperty::SetValue( wxVariant value
, wxVariant
* pList
, int flags 
) 
1221     // If auto unspecified values are not wanted (via window or property style), 
1222     // then get default value instead of wxNullVariant. 
1223     if ( value
.IsNull() && (flags 
& wxPG_SETVAL_BY_USER
) && 
1224          !UsesAutoUnspecified() ) 
1226         value 
= GetDefaultValue(); 
1229     if ( !value
.IsNull() ) 
1231         wxVariant tempListVariant
; 
1234         // List variants are reserved a special purpose 
1235         // as intermediate containers for child values 
1236         // of properties with children. 
1237         if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST 
) 
1240             // However, situation is different for composed string properties 
1241             if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) ) 
1243                 tempListVariant 
= value
; 
1244                 pList 
= &tempListVariant
; 
1248             AdaptListToValue(value
, &newValue
); 
1250             //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str()); 
1253         if ( HasFlag( wxPG_PROP_AGGREGATE
) ) 
1254             flags 
|= wxPG_SETVAL_AGGREGATED
; 
1256         if ( pList 
&& !pList
->IsNull() ) 
1258             wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST 
); 
1259             wxASSERT( GetChildCount() ); 
1260             wxASSERT( !IsCategory() ); 
1262             wxVariantList
& list 
= pList
->GetList(); 
1263             wxVariantList::iterator node
; 
1266             //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str()); 
1268             // Children in list can be in any order, but we will give hint to 
1269             // GetPropertyByNameWH(). This optimizes for full list parsing. 
1270             for ( node 
= list
.begin(); node 
!= list
.end(); ++node 
) 
1272                 wxVariant
& childValue 
= *((wxVariant
*)*node
); 
1273                 wxPGProperty
* child 
= GetPropertyByNameWH(childValue
.GetName(), i
); 
1276                     //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str()); 
1277                     if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST 
) 
1279                         if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags 
& wxPG_SETVAL_AGGREGATED
) ) 
1281                             wxVariant listRefCopy 
= childValue
; 
1282                             child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
); 
1286                             wxVariant oldVal 
= child
->GetValue(); 
1287                             child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
); 
1290                     else if ( child
->GetValue() != childValue 
) 
1292                         // For aggregate properties, we will trust RefreshChildren() 
1293                         // to update child values. 
1294                         if ( !HasFlag(wxPG_PROP_AGGREGATE
) ) 
1295                             child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
); 
1296                         if ( flags 
& wxPG_SETVAL_BY_USER 
) 
1297                             child
->SetFlag(wxPG_PROP_MODIFIED
); 
1304         if ( !value
.IsNull() ) 
1310         if ( flags 
& wxPG_SETVAL_BY_USER 
) 
1311             SetFlag(wxPG_PROP_MODIFIED
); 
1313         if ( HasFlag(wxPG_PROP_AGGREGATE
) ) 
1318         if ( m_commonValue 
!= -1 ) 
1320             wxPropertyGrid
* pg 
= GetGrid(); 
1321             if ( !pg 
|| m_commonValue 
!= pg
->GetUnspecifiedCommonValue() ) 
1327         // Set children to unspecified, but only if aggregate or 
1328         // value is <composed> 
1329         if ( AreChildrenComponents() ) 
1332             for ( i
=0; i
<GetChildCount(); i
++ ) 
1333                 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
); 
1337     if ( !(flags 
& wxPG_SETVAL_FROM_PARENT
) ) 
1338         UpdateParentValues(); 
1341     // Update editor control 
1344     // We need to check for these, otherwise GetGrid() may fail. 
1345     if ( flags 
& wxPG_SETVAL_REFRESH_EDITOR 
) 
1348         wxPropertyGrid
* pg 
= GetGridIfDisplayed(); 
1350             pg
->DrawItemAndValueRelated(this); 
1355 void wxPGProperty::SetValueInEvent( wxVariant value 
) const 
1357     GetGrid()->ValueChangeInEvent(value
); 
1360 void wxPGProperty::SetFlagRecursively( FlagType flag
, bool set 
) 
1368     for ( i 
= 0; i 
< GetChildCount(); i
++ ) 
1369         Item(i
)->SetFlagRecursively(flag
, set
); 
1372 void wxPGProperty::RefreshEditor() 
1377     wxPropertyGrid
* pg 
= GetGrid(); 
1378     if ( pg 
&& pg
->GetSelectedProperty() == this ) 
1379         pg
->RefreshEditor(); 
1382 wxVariant 
wxPGProperty::GetDefaultValue() const 
1384     wxVariant defVal 
= GetAttribute(wxS("DefaultValue")); 
1385     if ( !defVal
.IsNull() ) 
1388     wxVariant value 
= GetValue(); 
1390     if ( !value
.IsNull() ) 
1392         wxString 
valueType(value
.GetType()); 
1394         if ( valueType 
== wxPG_VARIANT_TYPE_LONG 
) 
1395             return wxPGVariant_Zero
; 
1396         if ( valueType 
== wxPG_VARIANT_TYPE_STRING 
) 
1397             return wxPGVariant_EmptyString
; 
1398         if ( valueType 
== wxPG_VARIANT_TYPE_BOOL 
) 
1399             return wxPGVariant_False
; 
1400         if ( valueType 
== wxPG_VARIANT_TYPE_DOUBLE 
) 
1401             return wxVariant(0.0); 
1402         if ( valueType 
== wxPG_VARIANT_TYPE_ARRSTRING 
) 
1403             return wxVariant(wxArrayString()); 
1404         if ( valueType 
== wxS("wxLongLong") ) 
1405             return WXVARIANT(wxLongLong(0)); 
1406         if ( valueType 
== wxS("wxULongLong") ) 
1407             return WXVARIANT(wxULongLong(0)); 
1408         if ( valueType 
== wxS("wxColour") ) 
1409             return WXVARIANT(*wxBLACK
); 
1411         if ( valueType 
== wxPG_VARIANT_TYPE_DATETIME 
) 
1412             return wxVariant(wxDateTime::Now()); 
1414         if ( valueType 
== wxS("wxFont") ) 
1415             return WXVARIANT(*wxNORMAL_FONT
); 
1416         if ( valueType 
== wxS("wxPoint") ) 
1417             return WXVARIANT(wxPoint(0, 0)); 
1418         if ( valueType 
== wxS("wxSize") ) 
1419             return WXVARIANT(wxSize(0, 0)); 
1425 void wxPGProperty::EnsureCells( unsigned int column 
) 
1427     if ( column 
>= m_cells
.size() ) 
1429         // Fill empty slots with default cells 
1430         wxPropertyGrid
* pg 
= GetGrid(); 
1431         wxPGCell defaultCell
; 
1433         if ( !HasFlag(wxPG_PROP_CATEGORY
) ) 
1434             defaultCell 
= pg
->GetPropertyDefaultCell(); 
1436             defaultCell 
= pg
->GetCategoryDefaultCell(); 
1438         // TODO: Replace with resize() call 
1439         unsigned int cellCountMax 
= column
+1; 
1441         for ( unsigned int i
=m_cells
.size(); i
<cellCountMax
; i
++ ) 
1442             m_cells
.push_back(defaultCell
); 
1446 void wxPGProperty::SetCell( int column
, 
1447                             const wxPGCell
& cell 
) 
1449     EnsureCells(column
); 
1451     m_cells
[column
] = cell
; 
1454 void wxPGProperty::AdaptiveSetCell( unsigned int firstCol
, 
1455                                     unsigned int lastCol
, 
1456                                     const wxPGCell
& cell
, 
1457                                     const wxPGCell
& srcData
, 
1458                                     wxPGCellData
* unmodCellData
, 
1459                                     FlagType ignoreWithFlags
, 
1463     // Sets cell in memory optimizing fashion. That is, if 
1464     // current cell data matches unmodCellData, we will 
1465     // simply get reference to data from cell. Otherwise, 
1466     // cell information from srcData is merged into current. 
1469     if ( !(m_flags 
& ignoreWithFlags
) && !IsRoot() ) 
1471         EnsureCells(lastCol
); 
1473         for ( unsigned int col
=firstCol
; col
<=lastCol
; col
++ ) 
1475             if ( m_cells
[col
].GetData() == unmodCellData 
) 
1477                 // Data matches... use cell directly 
1478                 m_cells
[col
] = cell
; 
1482                 // Data did not match... merge valid information 
1483                 m_cells
[col
].MergeFrom(srcData
); 
1490         for ( unsigned int i
=0; i
<GetChildCount(); i
++ ) 
1491             Item(i
)->AdaptiveSetCell( firstCol
, 
1501 const wxPGCell
& wxPGProperty::GetCell( unsigned int column 
) const 
1503     if ( m_cells
.size() > column 
) 
1504         return m_cells
[column
]; 
1506     wxPropertyGrid
* pg 
= GetGrid(); 
1509         return pg
->GetCategoryDefaultCell(); 
1511     return pg
->GetPropertyDefaultCell(); 
1514 wxPGCell
& wxPGProperty::GetCell( unsigned int column 
) 
1516     EnsureCells(column
); 
1517     return m_cells
[column
]; 
1520 void wxPGProperty::SetBackgroundColour( const wxColour
& colour
, 
1523     wxPGProperty
* firstProp 
= this; 
1526     // If category is tried to set recursively, skip it and only 
1527     // affect the children. 
1530         while ( firstProp
->IsCategory() ) 
1532             if ( !firstProp
->GetChildCount() ) 
1534             firstProp 
= firstProp
->Item(0); 
1538     wxPGCell
& firstCell 
= firstProp
->GetCell(0); 
1539     wxPGCellData
* firstCellData 
= firstCell
.GetData(); 
1541     wxPGCell 
newCell(firstCell
); 
1542     newCell
.SetBgCol(colour
); 
1544     srcCell
.SetBgCol(colour
); 
1547                      GetParentState()->GetColumnCount()-1, 
1551                      recursively 
? wxPG_PROP_CATEGORY 
: 0, 
1555 void wxPGProperty::SetTextColour( const wxColour
& colour
, 
1558     wxPGProperty
* firstProp 
= this; 
1561     // If category is tried to set recursively, skip it and only 
1562     // affect the children. 
1565         while ( firstProp
->IsCategory() ) 
1567             if ( !firstProp
->GetChildCount() ) 
1569             firstProp 
= firstProp
->Item(0); 
1573     wxPGCell
& firstCell 
= firstProp
->GetCell(0); 
1574     wxPGCellData
* firstCellData 
= firstCell
.GetData(); 
1576     wxPGCell 
newCell(firstCell
); 
1577     newCell
.SetFgCol(colour
); 
1579     srcCell
.SetFgCol(colour
); 
1582                      GetParentState()->GetColumnCount()-1, 
1586                      recursively 
? wxPG_PROP_CATEGORY 
: 0, 
1590 wxPGEditorDialogAdapter
* wxPGProperty::GetEditorDialog() const 
1595 bool wxPGProperty::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) ) 
1600 void wxPGProperty::SetAttribute( const wxString
& name
, wxVariant value 
) 
1602     if ( DoSetAttribute( name
, value 
) ) 
1604         // Support working without grid, when possible 
1605         if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES 
) ) 
1609     m_attributes
.Set( name
, value 
); 
1612 void wxPGProperty::SetAttributes( const wxPGAttributeStorage
& attributes 
) 
1614     wxPGAttributeStorage::const_iterator it 
= attributes
.StartIteration(); 
1617     while ( attributes
.GetNext(it
, variant
) ) 
1618         SetAttribute( variant
.GetName(), variant 
); 
1621 wxVariant 
wxPGProperty::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const 
1627 wxVariant 
wxPGProperty::GetAttribute( const wxString
& name 
) const 
1629     return m_attributes
.FindValue(name
); 
1632 wxString 
wxPGProperty::GetAttribute( const wxString
& name
, const wxString
& defVal 
) const 
1634     wxVariant variant 
= m_attributes
.FindValue(name
); 
1636     if ( !variant
.IsNull() ) 
1637         return variant
.GetString(); 
1642 long wxPGProperty::GetAttributeAsLong( const wxString
& name
, long defVal 
) const 
1644     wxVariant variant 
= m_attributes
.FindValue(name
); 
1646     return wxPGVariantToInt(variant
, defVal
); 
1649 double wxPGProperty::GetAttributeAsDouble( const wxString
& name
, double defVal 
) const 
1652     wxVariant variant 
= m_attributes
.FindValue(name
); 
1654     if ( wxPGVariantToDouble(variant
, &retVal
) ) 
1660 wxVariant 
wxPGProperty::GetAttributesAsList() const 
1662     wxVariantList tempList
; 
1663     wxVariant 
v( tempList
, wxString::Format(wxS("@%s@attr"),m_name
.c_str()) ); 
1665     wxPGAttributeStorage::const_iterator it 
= m_attributes
.StartIteration(); 
1668     while ( m_attributes
.GetNext(it
, variant
) ) 
1674 // Slots of utility flags are NULL 
1675 const unsigned int gs_propFlagToStringSize 
= 14; 
1677 static const wxChar
* gs_propFlagToString
[gs_propFlagToStringSize
] = { 
1694 wxString 
wxPGProperty::GetFlagsAsString( FlagType flagsMask 
) const 
1697     int relevantFlags 
= m_flags 
& flagsMask 
& wxPG_STRING_STORED_FLAGS
; 
1701     for ( i
=0; i
<gs_propFlagToStringSize
; i
++ ) 
1703         if ( relevantFlags 
& a 
) 
1705             const wxChar
* fs 
= gs_propFlagToString
[i
]; 
1717 void wxPGProperty::SetFlagsFromString( const wxString
& str 
) 
1721     WX_PG_TOKENIZER1_BEGIN(str
, wxS('|')) 
1723         for ( i
=0; i
<gs_propFlagToStringSize
; i
++ ) 
1725             const wxChar
* fs 
= gs_propFlagToString
[i
]; 
1726             if ( fs 
&& str 
== fs 
) 
1732     WX_PG_TOKENIZER1_END() 
1734     m_flags 
= (m_flags 
& ~wxPG_STRING_STORED_FLAGS
) | flags
; 
1737 wxValidator
* wxPGProperty::DoGetValidator() const 
1742 int wxPGProperty::InsertChoice( const wxString
& label
, int index
, int value 
) 
1744     wxPropertyGrid
* pg 
= GetGrid(); 
1745     int sel 
= GetChoiceSelection(); 
1749     if ( index 
== wxNOT_FOUND 
) 
1750         index 
= m_choices
.GetCount(); 
1755     m_choices
.Insert(label
, index
, value
); 
1757     if ( sel 
!= newSel 
) 
1758         SetChoiceSelection(newSel
); 
1760     if ( this == pg
->GetSelection() ) 
1761         GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
); 
1767 void wxPGProperty::DeleteChoice( int index 
) 
1769     wxPropertyGrid
* pg 
= GetGrid(); 
1771     int sel 
= GetChoiceSelection(); 
1774     // Adjust current value 
1777         SetValueToUnspecified(); 
1780     else if ( index 
< sel 
) 
1785     m_choices
.RemoveAt(index
); 
1787     if ( sel 
!= newSel 
) 
1788         SetChoiceSelection(newSel
); 
1790     if ( this == pg
->GetSelection() ) 
1791         GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
); 
1794 int wxPGProperty::GetChoiceSelection() const 
1796     wxVariant value 
= GetValue(); 
1797     wxString valueType 
= value
.GetType(); 
1798     int index 
= wxNOT_FOUND
; 
1800     if ( IsValueUnspecified() || !m_choices
.GetCount() ) 
1803     if ( valueType 
== wxPG_VARIANT_TYPE_LONG 
) 
1805         index 
= value
.GetLong(); 
1807     else if ( valueType 
== wxPG_VARIANT_TYPE_STRING 
) 
1809         index 
= m_choices
.Index(value
.GetString()); 
1811     else if ( valueType 
== wxPG_VARIANT_TYPE_BOOL 
) 
1813         index 
= value
.GetBool()? 1 : 0; 
1819 void wxPGProperty::SetChoiceSelection( int newValue 
) 
1821     // Changes value of a property with choices, but only 
1822     // works if the value type is long or string. 
1823     wxString valueType 
= GetValue().GetType(); 
1825     wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") ); 
1827     if ( valueType 
== wxPG_VARIANT_TYPE_STRING 
) 
1829         SetValue( m_choices
.GetLabel(newValue
) ); 
1831     else  // if ( valueType == wxPG_VARIANT_TYPE_LONG ) 
1833         SetValue( (long) newValue 
); 
1837 bool wxPGProperty::SetChoices( wxPGChoices
& choices 
) 
1839     m_choices
.Assign(choices
); 
1842         // This may be needed to trigger some initialization 
1843         // (but don't do it if property is somewhat uninitialized) 
1844         wxVariant defVal 
= GetDefaultValue(); 
1845         if ( defVal
.IsNull() ) 
1855 const wxPGEditor
* wxPGProperty::GetEditorClass() const 
1857     const wxPGEditor
* editor
; 
1859     if ( !m_customEditor 
) 
1861         editor 
= DoGetEditorClass(); 
1864         editor 
= m_customEditor
; 
1867     // Maybe override editor if common value specified 
1868     if ( GetDisplayedCommonValueCount() ) 
1870         // TextCtrlAndButton -> ComboBoxAndButton 
1871         if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) ) 
1872             editor 
= wxPGEditor_ChoiceAndButton
; 
1874         // TextCtrl -> ComboBox 
1875         else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) ) 
1876             editor 
= wxPGEditor_ComboBox
; 
1882 bool wxPGProperty::HasVisibleChildren() const 
1886     for ( i
=0; i
<GetChildCount(); i
++ ) 
1888         wxPGProperty
* child 
= Item(i
); 
1890         if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) ) 
1897 bool wxPGProperty::RecreateEditor() 
1899     wxPropertyGrid
* pg 
= GetGrid(); 
1902     wxPGProperty
* selected 
= pg
->GetSelection(); 
1903     if ( this == selected 
) 
1905         pg
->DoSelectProperty(this, wxPG_SEL_FORCE
); 
1912 void wxPGProperty::SetValueImage( wxBitmap
& bmp 
) 
1914     delete m_valueBitmap
; 
1916     if ( &bmp 
&& bmp
.Ok() ) 
1919         wxSize maxSz 
= GetGrid()->GetImageSize(); 
1920         wxSize 
imSz(bmp
.GetWidth(),bmp
.GetHeight()); 
1922         if ( imSz
.y 
!= maxSz
.y 
) 
1924             // Create a memory DC 
1925             wxBitmap
* bmpNew 
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth()); 
1928             dc
.SelectObject(*bmpNew
); 
1931             // FIXME: This is ugly - use image or wait for scaling patch. 
1932             double scaleY 
= (double)maxSz
.y 
/ (double)imSz
.y
; 
1934             dc
.SetUserScale(scaleY
, scaleY
); 
1936             dc
.DrawBitmap(bmp
, 0, 0); 
1938             m_valueBitmap 
= bmpNew
; 
1942             m_valueBitmap 
= new wxBitmap(bmp
); 
1945         m_flags 
|= wxPG_PROP_CUSTOMIMAGE
; 
1949         m_valueBitmap 
= NULL
; 
1950         m_flags 
&= ~(wxPG_PROP_CUSTOMIMAGE
); 
1955 wxPGProperty
* wxPGProperty::GetMainParent() const 
1957     const wxPGProperty
* curChild 
= this; 
1958     const wxPGProperty
* curParent 
= m_parent
; 
1960     while ( curParent 
&& !curParent
->IsCategory() ) 
1962         curChild 
= curParent
; 
1963         curParent 
= curParent
->m_parent
; 
1966     return (wxPGProperty
*) curChild
; 
1970 const wxPGProperty
* wxPGProperty::GetLastVisibleSubItem() const 
1973     // Returns last visible sub-item, recursively. 
1974     if ( !IsExpanded() || !GetChildCount() ) 
1977     return Last()->GetLastVisibleSubItem(); 
1981 bool wxPGProperty::IsVisible() const 
1983     const wxPGProperty
* parent
; 
1985     if ( HasFlag(wxPG_PROP_HIDDEN
) ) 
1988     for ( parent 
= GetParent(); parent 
!= NULL
; parent 
= parent
->GetParent() ) 
1990         if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) ) 
1997 wxPropertyGrid
* wxPGProperty::GetGridIfDisplayed() const 
1999     wxPropertyGridPageState
* state 
= GetParentState(); 
2002     wxPropertyGrid
* propGrid 
= state
->GetGrid(); 
2003     if ( state 
== propGrid
->GetState() ) 
2009 int wxPGProperty::GetY2( int lh 
) const 
2011     const wxPGProperty
* parent
; 
2012     const wxPGProperty
* child 
= this; 
2016     for ( parent 
= GetParent(); parent 
!= NULL
; parent 
= child
->GetParent() ) 
2018         if ( !parent
->IsExpanded() ) 
2020         y 
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent()); 
2025     y 
-= lh
;  // need to reduce one level 
2031 int wxPGProperty::GetY() const 
2033     return GetY2(GetGrid()->GetRowHeight()); 
2036 // This is used by Insert etc. 
2037 void wxPGProperty::AddChild2( wxPGProperty
* prop
, int index
, bool correct_mode 
) 
2039     if ( index 
< 0 || (size_t)index 
>= m_children
.size() ) 
2041         if ( correct_mode 
) prop
->m_arrIndex 
= m_children
.size(); 
2042         m_children
.push_back( prop 
); 
2046         m_children
.insert( m_children
.begin()+index
, prop
); 
2047         if ( correct_mode 
) FixIndicesOfChildren( index 
); 
2050     prop
->m_parent 
= this; 
2053 // This is used by properties that have fixed sub-properties 
2054 void wxPGProperty::AddChild( wxPGProperty
* prop 
) 
2056     wxASSERT_MSG( prop
->GetBaseName().length(), 
2057                   "Property's children must have unique, non-empty names within their scope" ); 
2059     prop
->m_arrIndex 
= m_children
.size(); 
2060     m_children
.push_back( prop 
); 
2062     int custImgHeight 
= prop
->OnMeasureImage().y
; 
2063     if ( custImgHeight 
< 0 /*|| custImgHeight > 1*/ ) 
2064         prop
->m_flags 
|= wxPG_PROP_CUSTOMIMAGE
; 
2066     prop
->m_parent 
= this; 
2069 void wxPGProperty::RemoveChild( wxPGProperty
* p 
) 
2071     wxArrayPGProperty::iterator it
; 
2072     wxArrayPGProperty
& children 
= m_children
; 
2074     for ( it
=children
.begin(); it 
!= children
.end(); it
++ ) 
2078             m_children
.erase(it
); 
2084 void wxPGProperty::AdaptListToValue( wxVariant
& list
, wxVariant
* value 
) const 
2086     wxASSERT( GetChildCount() ); 
2087     wxASSERT( !IsCategory() ); 
2089     *value 
= GetValue(); 
2091     if ( !list
.GetCount() ) 
2094     wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() ); 
2096     bool allChildrenSpecified
; 
2098     // Don't fully update aggregate properties unless all children have 
2100     if ( HasFlag(wxPG_PROP_AGGREGATE
) ) 
2101         allChildrenSpecified 
= AreAllChildrenSpecified(&list
); 
2103         allChildrenSpecified 
= true; 
2105     wxVariant childValue 
= list
[0]; 
2109     //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str()); 
2111     for ( i
=0; i
<GetChildCount(); i
++ ) 
2113         const wxPGProperty
* child 
= Item(i
); 
2115         if ( childValue
.GetName() == child
->GetBaseName() ) 
2117             //wxLogDebug(wxT("  %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str()); 
2119             if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST 
) 
2121                 wxVariant 
cv2(child
->GetValue()); 
2122                 child
->AdaptListToValue(childValue
, &cv2
); 
2126             if ( allChildrenSpecified 
) 
2127                 ChildChanged(*value
, i
, childValue
); 
2129             if ( n 
== (unsigned int)list
.GetCount() ) 
2131             childValue 
= list
[n
]; 
2137 void wxPGProperty::FixIndicesOfChildren( unsigned int starthere 
) 
2140     for ( i
=starthere
;i
<GetChildCount();i
++) 
2141         Item(i
)->m_arrIndex 
= i
; 
2145 // Returns (direct) child property with given name (or NULL if not found) 
2146 wxPGProperty
* wxPGProperty::GetPropertyByName( const wxString
& name 
) const 
2150     for ( i
=0; i
<GetChildCount(); i
++ ) 
2152         wxPGProperty
* p 
= Item(i
); 
2153         if ( p
->m_name 
== name 
) 
2157     // Does it have point, then? 
2158     int pos 
= name
.Find(wxS('.')); 
2162     wxPGProperty
* p 
= GetPropertyByName(name
. substr(0,pos
)); 
2164     if ( !p 
|| !p
->GetChildCount() ) 
2167     return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1)); 
2170 wxPGProperty
* wxPGProperty::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex 
) const 
2172     unsigned int i 
= hintIndex
; 
2174     if ( i 
>= GetChildCount() ) 
2177     unsigned int lastIndex 
= i 
- 1; 
2179     if ( lastIndex 
>= GetChildCount() ) 
2180         lastIndex 
= GetChildCount() - 1; 
2184         wxPGProperty
* p 
= Item(i
); 
2185         if ( p
->m_name 
== name 
) 
2188         if ( i 
== lastIndex 
) 
2192         if ( i 
== GetChildCount() ) 
2199 int wxPGProperty::GetChildrenHeight( int lh
, int iMax_ 
) const 
2201     // Returns height of children, recursively, and 
2202     // by taking expanded/collapsed status into account. 
2204     // iMax is used when finding property y-positions. 
2210         iMax_ 
= GetChildCount(); 
2212     unsigned int iMax 
= iMax_
; 
2214     wxASSERT( iMax 
<= GetChildCount() ); 
2216     if ( !IsExpanded() && GetParent() ) 
2221         wxPGProperty
* pwc 
= (wxPGProperty
*) Item(i
); 
2223         if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) ) 
2225             if ( !pwc
->IsExpanded() || 
2226                  pwc
->GetChildCount() == 0 ) 
2229                 h 
+= pwc
->GetChildrenHeight(lh
) + lh
; 
2238 wxPGProperty
* wxPGProperty::GetItemAtY( unsigned int y
, unsigned int lh
, unsigned int* nextItemY 
) const 
2240     wxASSERT( nextItemY 
); 
2242     // Linear search at the moment 
2244     // nextItemY = y of next visible property, final value will be written back. 
2245     wxPGProperty
* result 
= NULL
; 
2246     wxPGProperty
* current 
= NULL
; 
2247     unsigned int iy 
= *nextItemY
; 
2249     unsigned int iMax 
= GetChildCount(); 
2253         wxPGProperty
* pwc 
= Item(i
); 
2255         if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) ) 
2266             if ( pwc
->IsExpanded() && 
2267                  pwc
->GetChildCount() > 0 ) 
2269                 result 
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy 
); 
2281     if ( !result 
&& y 
< iy 
) 
2288         wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str()); 
2290         wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y); 
2293     return (wxPGProperty
*) result
; 
2296 void wxPGProperty::Empty() 
2299     if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) ) 
2301         for ( i
=0; i
<GetChildCount(); i
++ ) 
2303             delete m_children
[i
]; 
2310 void wxPGProperty::DeleteChildren() 
2312     wxPropertyGridPageState
* state 
= m_parentState
; 
2314     while ( GetChildCount() ) 
2316         wxPGProperty
* child 
= Item(GetChildCount()-1); 
2317         state
->DoDelete(child
, true); 
2321 void wxPGProperty::ChildChanged( wxVariant
& WXUNUSED(thisValue
), 
2322                                  int WXUNUSED(childIndex
), 
2323                                  wxVariant
& WXUNUSED(childValue
) ) const 
2327 bool wxPGProperty::AreAllChildrenSpecified( wxVariant
* pendingList 
) const 
2331     const wxVariantList
* pList 
= NULL
; 
2332     wxVariantList::const_iterator node
; 
2336         pList 
= &pendingList
->GetList(); 
2337         node 
= pList
->begin(); 
2340     for ( i
=0; i
<GetChildCount(); i
++ ) 
2342         wxPGProperty
* child 
= Item(i
); 
2343         const wxVariant
* listValue 
= NULL
; 
2348             const wxString
& childName 
= child
->GetBaseName(); 
2350             for ( ; node 
!= pList
->end(); ++node 
) 
2352                 const wxVariant
& item 
= *((const wxVariant
*)*node
); 
2353                 if ( item
.GetName() == childName 
) 
2363             value 
= child
->GetValue(); 
2365         if ( value
.IsNull() ) 
2368         // Check recursively 
2369         if ( child
->GetChildCount() ) 
2371             const wxVariant
* childList 
= NULL
; 
2373             if ( listValue 
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST 
) 
2374                 childList 
= listValue
; 
2376             if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) ) 
2384 wxPGProperty
* wxPGProperty::UpdateParentValues() 
2386     wxPGProperty
* parent 
= m_parent
; 
2387     if ( parent 
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) && 
2388          !parent
->IsCategory() && !parent
->IsRoot() ) 
2391         parent
->DoGenerateComposedValue(s
); 
2392         parent
->m_value 
= s
; 
2393         return parent
->UpdateParentValues(); 
2398 bool wxPGProperty::IsTextEditable() const 
2400     if ( HasFlag(wxPG_PROP_READONLY
) ) 
2403     if ( HasFlag(wxPG_PROP_NOEDITOR
) && 
2405           wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button"))) 
2412 // Call after fixed sub-properties added/removed after creation. 
2413 // if oldSelInd >= 0 and < new max items, then selection is 
2414 // moved to it. Note: oldSelInd -2 indicates that this property 
2415 // should be selected. 
2416 void wxPGProperty::SubPropsChanged( int oldSelInd 
) 
2418     wxPropertyGridPageState
* state 
= GetParentState(); 
2419     wxPropertyGrid
* grid 
= state
->GetGrid(); 
2422     // Re-repare children (recursively) 
2423     for ( unsigned int i
=0; i
<GetChildCount(); i
++ ) 
2425         wxPGProperty
* child 
= Item(i
); 
2426         child
->InitAfterAdded(state
, grid
); 
2429     wxPGProperty
* sel 
= NULL
; 
2430     if ( oldSelInd 
>= (int)m_children
.size() ) 
2431         oldSelInd 
= (int)m_children
.size() - 1; 
2433     if ( oldSelInd 
>= 0 ) 
2434         sel 
= m_children
[oldSelInd
]; 
2435     else if ( oldSelInd 
== -2 ) 
2439         state
->DoSelectProperty(sel
); 
2441     if ( state 
== grid
->GetState() ) 
2443         grid
->GetPanel()->Refresh(); 
2447 // ----------------------------------------------------------------------- 
2449 // ----------------------------------------------------------------------- 
2451 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
) 
2452 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
) 
2455 wxPGRootProperty::wxPGRootProperty( const wxString
& name 
) 
2469 wxPGRootProperty::~wxPGRootProperty() 
2474 // ----------------------------------------------------------------------- 
2475 // wxPropertyCategory 
2476 // ----------------------------------------------------------------------- 
2478 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
) 
2479 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
) 
2481 void wxPropertyCategory::Init() 
2483     // don't set colour - prepareadditem method should do this 
2484     SetParentalType(wxPG_PROP_CATEGORY
); 
2485     m_capFgColIndex 
= 1; 
2489 wxPropertyCategory::wxPropertyCategory() 
2496 wxPropertyCategory::wxPropertyCategory( const wxString 
&label
, const wxString
& name 
) 
2497     : wxPGProperty(label
,name
) 
2503 wxPropertyCategory::~wxPropertyCategory() 
2508 wxString 
wxPropertyCategory::ValueToString( wxVariant
& WXUNUSED(value
), 
2509                                             int WXUNUSED(argFlags
) ) const 
2511     return wxEmptyString
; 
2514 int wxPropertyCategory::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font 
) const 
2516     if ( m_textExtent 
> 0 ) 
2517         return m_textExtent
; 
2519         ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font 
); 
2523 void wxPropertyCategory::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font 
) 
2526         wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font 
); 
2530 // ----------------------------------------------------------------------- 
2532 // ----------------------------------------------------------------------- 
2534 wxPGChoiceEntry
& wxPGChoices::Add( const wxString
& label
, int value 
) 
2538     wxPGChoiceEntry 
entry(label
, value
); 
2539     return m_data
->Insert( -1, entry 
); 
2542 // ----------------------------------------------------------------------- 
2544 wxPGChoiceEntry
& wxPGChoices::Add( const wxString
& label
, const wxBitmap
& bitmap
, int value 
) 
2548     wxPGChoiceEntry 
entry(label
, value
); 
2549     entry
.SetBitmap(bitmap
); 
2550     return m_data
->Insert( -1, entry 
); 
2553 // ----------------------------------------------------------------------- 
2555 wxPGChoiceEntry
& wxPGChoices::Insert( const wxPGChoiceEntry
& entry
, int index 
) 
2559     return m_data
->Insert( index
, entry 
); 
2562 // ----------------------------------------------------------------------- 
2564 wxPGChoiceEntry
& wxPGChoices::Insert( const wxString
& label
, int index
, int value 
) 
2568     wxPGChoiceEntry 
entry(label
, value
); 
2569     return m_data
->Insert( index
, entry 
); 
2572 // ----------------------------------------------------------------------- 
2574 wxPGChoiceEntry
& wxPGChoices::AddAsSorted( const wxString
& label
, int value 
) 
2580     while ( index 
< GetCount() ) 
2582         int cmpRes 
= GetLabel(index
).Cmp(label
); 
2588     wxPGChoiceEntry 
entry(label
, value
); 
2589     return m_data
->Insert( index
, entry 
); 
2592 // ----------------------------------------------------------------------- 
2594 void wxPGChoices::Add( const wxChar
** labels
, const ValArrItem
* values 
) 
2598     unsigned int itemcount 
= 0; 
2599     const wxChar
** p 
= &labels
[0]; 
2600     while ( *p 
) { p
++; itemcount
++; } 
2603     for ( i 
= 0; i 
< itemcount
; i
++ ) 
2608         wxPGChoiceEntry 
entry(labels
[i
], value
); 
2609         m_data
->Insert( i
, entry 
); 
2613 // ----------------------------------------------------------------------- 
2615 void wxPGChoices::Add( const wxArrayString
& arr
, const wxArrayInt
& arrint 
) 
2620     unsigned int itemcount 
= arr
.size(); 
2622     for ( i 
= 0; i 
< itemcount
; i
++ ) 
2625         if ( &arrint 
&& arrint
.size() ) 
2627         wxPGChoiceEntry 
entry(arr
[i
], value
); 
2628         m_data
->Insert( i
, entry 
); 
2632 // ----------------------------------------------------------------------- 
2634 void wxPGChoices::RemoveAt(size_t nIndex
, size_t count
) 
2638     wxASSERT( m_data
->m_refCount 
!= 0xFFFFFFF ); 
2639     m_data
->m_items
.erase(m_data
->m_items
.begin()+nIndex
, 
2640                           m_data
->m_items
.begin()+nIndex
+count
); 
2643 // ----------------------------------------------------------------------- 
2645 void wxPGChoices::Clear() 
2647     if ( m_data 
!= wxPGChoicesEmptyData 
) 
2654 // ----------------------------------------------------------------------- 
2656 int wxPGChoices::Index( const wxString
& str 
) const 
2661         for ( i
=0; i
< m_data
->GetCount(); i
++ ) 
2663             const wxPGChoiceEntry
& entry 
= m_data
->Item(i
); 
2664             if ( entry
.HasText() && entry
.GetText() == str 
) 
2671 // ----------------------------------------------------------------------- 
2673 int wxPGChoices::Index( int val 
) const 
2678         for ( i
=0; i
< m_data
->GetCount(); i
++ ) 
2680             const wxPGChoiceEntry
& entry 
= m_data
->Item(i
); 
2681             if ( entry
.GetValue() == val 
) 
2688 // ----------------------------------------------------------------------- 
2690 wxArrayString 
wxPGChoices::GetLabels() const 
2695     if ( this && IsOk() ) 
2696         for ( i
=0; i
<GetCount(); i
++ ) 
2697             arr
.push_back(GetLabel(i
)); 
2702 // ----------------------------------------------------------------------- 
2704 wxArrayInt 
wxPGChoices::GetValuesForStrings( const wxArrayString
& strings 
) const 
2711         for ( i
=0; i
< strings
.size(); i
++ ) 
2713             int index 
= Index(strings
[i
]); 
2715                 arr
.Add(GetValue(index
)); 
2717                 arr
.Add(wxPG_INVALID_VALUE
); 
2724 // ----------------------------------------------------------------------- 
2726 wxArrayInt 
wxPGChoices::GetIndicesForStrings( const wxArrayString
& strings
, 
2727                                               wxArrayString
* unmatched 
) const 
2734         for ( i
=0; i
< strings
.size(); i
++ ) 
2736             const wxString
& str 
= strings
[i
]; 
2737             int index 
= Index(str
); 
2740             else if ( unmatched 
) 
2741                 unmatched
->Add(str
); 
2748 // ----------------------------------------------------------------------- 
2750 void wxPGChoices::AllocExclusive() 
2754     if ( m_data
->m_refCount 
!= 1 ) 
2756         wxPGChoicesData
* data 
= new wxPGChoicesData(); 
2757         data
->CopyDataFrom(m_data
); 
2763 // ----------------------------------------------------------------------- 
2765 void wxPGChoices::AssignData( wxPGChoicesData
* data 
) 
2769     if ( data 
!= wxPGChoicesEmptyData 
) 
2776 // ----------------------------------------------------------------------- 
2778 void wxPGChoices::Init() 
2780     m_data 
= wxPGChoicesEmptyData
; 
2783 // ----------------------------------------------------------------------- 
2785 void wxPGChoices::Free() 
2787     if ( m_data 
!= wxPGChoicesEmptyData 
) 
2790         m_data 
= wxPGChoicesEmptyData
; 
2794 // ----------------------------------------------------------------------- 
2795 // wxPGAttributeStorage 
2796 // ----------------------------------------------------------------------- 
2798 wxPGAttributeStorage::wxPGAttributeStorage() 
2802 wxPGAttributeStorage::~wxPGAttributeStorage() 
2804     wxPGHashMapS2P::iterator it
; 
2806     for ( it 
= m_map
.begin(); it 
!= m_map
.end(); ++it 
) 
2808         wxVariantData
* data 
= (wxVariantData
*) it
->second
; 
2813 void wxPGAttributeStorage::Set( const wxString
& name
, const wxVariant
& value 
) 
2815     wxVariantData
* data 
= value
.GetData(); 
2818     wxPGHashMapS2P::iterator it 
= m_map
.find(name
); 
2819     if ( it 
!= m_map
.end() ) 
2821         ((wxVariantData
*)it
->second
)->DecRef(); 
2825             // If Null variant, just remove from set 
2839 #endif  // wxUSE_PROPGRID