1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/propgrid/props.cpp 
   3 // Purpose:     Basic Property Classes 
   4 // Author:      Jaakko Salli 
   8 // Copyright:   (c) Jaakko Salli 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx/wx.h". 
  13 #include "wx/wxprec.h" 
  23     #include "wx/object.h" 
  25     #include "wx/string.h" 
  28     #include "wx/window.h" 
  31     #include "wx/dcclient.h" 
  32     #include "wx/dcmemory.h" 
  33     #include "wx/button.h" 
  34     #include "wx/bmpbuttn.h" 
  37     #include "wx/cursor.h" 
  38     #include "wx/dialog.h" 
  39     #include "wx/settings.h" 
  40     #include "wx/msgdlg.h" 
  41     #include "wx/choice.h" 
  42     #include "wx/stattext.h" 
  43     #include "wx/scrolwin.h" 
  44     #include "wx/dirdlg.h" 
  45     #include "wx/combobox.h" 
  46     #include "wx/layout.h" 
  48     #include "wx/textdlg.h" 
  49     #include "wx/filedlg.h" 
  53 #include "wx/filename.h" 
  55 #include "wx/propgrid/propgrid.h" 
  57 #define wxPG_CUSTOM_IMAGE_WIDTH     20 // for wxColourProperty etc. 
  60 // ----------------------------------------------------------------------- 
  62 // ----------------------------------------------------------------------- 
  64 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty
,wxPGProperty
, 
  65                                wxString
,const wxString
&,TextCtrl
) 
  67 wxStringProperty::wxStringProperty( const wxString
& label
, 
  69                                     const wxString
& value 
) 
  70     : wxPGProperty(label
,name
) 
  75 void wxStringProperty::OnSetValue() 
  77     if ( !m_value
.IsNull() && m_value
.GetString() == wxS("<composed>") ) 
  78         SetFlag(wxPG_PROP_COMPOSED_VALUE
); 
  80     if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) ) 
  83         DoGenerateComposedValue(s
); 
  88 wxStringProperty::~wxStringProperty() { } 
  90 wxString 
wxStringProperty::ValueToString( wxVariant
& value
, 
  93     wxString s 
= value
.GetString(); 
  95     if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) ) 
  97         // Value stored in m_value is non-editable, non-full value 
  98         if ( (argFlags 
& wxPG_FULL_VALUE
) || 
  99              (argFlags 
& wxPG_EDITABLE_VALUE
) || 
 102             // Calling this under incorrect conditions will fail 
 103             wxASSERT_MSG( argFlags 
& wxPG_VALUE_IS_CURRENT
, 
 104                           "Sorry, currently default wxPGProperty::ValueToString() " 
 105                           "implementation only works if value is m_value." ); 
 107             DoGenerateComposedValue(s
, argFlags
); 
 113     // If string is password and value is for visual purposes, 
 114     // then return asterisks instead the actual string. 
 115     if ( (m_flags 
& wxPG_PROP_PASSWORD
) && !(argFlags 
& (wxPG_FULL_VALUE
|wxPG_EDITABLE_VALUE
)) ) 
 116         return wxString(wxChar('*'), s
.Length()); 
 121 bool wxStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags 
) const 
 123     if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) ) 
 124         return wxPGProperty::StringToValue(variant
, text
, argFlags
); 
 126     if ( variant 
!= text 
) 
 135 bool wxStringProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
 137     if ( name 
== wxPG_STRING_PASSWORD 
) 
 139         m_flags 
&= ~(wxPG_PROP_PASSWORD
); 
 140         if ( value
.GetLong() ) m_flags 
|= wxPG_PROP_PASSWORD
; 
 147 // ----------------------------------------------------------------------- 
 148 // wxNumericPropertyValidator 
 149 // ----------------------------------------------------------------------- 
 153 wxNumericPropertyValidator:: 
 154     wxNumericPropertyValidator( NumericType numericType
, int base 
) 
 155     : wxTextValidator(wxFILTER_INCLUDE_CHAR_LIST
) 
 173             arr
.Add(wxS("a")); arr
.Add(wxS("A")); 
 174             arr
.Add(wxS("b")); arr
.Add(wxS("B")); 
 175             arr
.Add(wxS("c")); arr
.Add(wxS("C")); 
 176             arr
.Add(wxS("d")); arr
.Add(wxS("D")); 
 177             arr
.Add(wxS("e")); arr
.Add(wxS("E")); 
 178             arr
.Add(wxS("f")); arr
.Add(wxS("F")); 
 182     if ( numericType 
== Signed 
) 
 187     else if ( numericType 
== Float 
) 
 193         // Use locale-specific decimal point 
 194         arr
.Add(wxString::Format("%g", 1.1)[1]); 
 200 bool wxNumericPropertyValidator::Validate(wxWindow
* parent
) 
 202     if ( !wxTextValidator::Validate(parent
) ) 
 205     wxWindow
* wnd 
= GetWindow(); 
 206     if ( !wnd
->IsKindOf(CLASSINFO(wxTextCtrl
)) ) 
 209     // Do not allow zero-length string 
 210     wxTextCtrl
* tc 
= static_cast<wxTextCtrl
*>(wnd
); 
 211     wxString text 
= tc
->GetValue(); 
 219 #endif // wxUSE_VALIDATORS 
 221 // ----------------------------------------------------------------------- 
 223 // ----------------------------------------------------------------------- 
 225 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty
,wxPGProperty
, 
 228 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
, 
 229     long value 
) : wxPGProperty(label
,name
) 
 234 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
, 
 235     const wxLongLong
& value 
) : wxPGProperty(label
,name
) 
 237     SetValue(WXVARIANT(value
)); 
 240 wxIntProperty::~wxIntProperty() { } 
 242 wxString 
wxIntProperty::ValueToString( wxVariant
& value
, 
 243                                        int WXUNUSED(argFlags
) ) const 
 245     if ( value
.GetType() == wxPG_VARIANT_TYPE_LONG 
) 
 247         return wxString::Format(wxS("%li"),value
.GetLong()); 
 249     else if ( value
.GetType() == wxPG_VARIANT_TYPE_LONGLONG 
) 
 251         wxLongLong ll 
= value
.GetLongLong(); 
 252         return ll
.ToString(); 
 255     return wxEmptyString
; 
 258 bool wxIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags 
) const 
 269     // We know it is a number, but let's still check 
 271     if ( text
.IsNumber() ) 
 273         // Remove leading zeroes, so that the number is not interpreted as octal 
 274         wxString::const_iterator i 
= text
.begin(); 
 275         wxString::const_iterator iMax 
= text
.end() - 1;  // Let's allow one, last zero though 
 277         int firstNonZeroPos 
= 0; 
 279         for ( ; i 
!= iMax
; ++i 
) 
 282             if ( c 
!= wxS('0') && c 
!= wxS(' ') ) 
 287         wxString useText 
= text
.substr(firstNonZeroPos
, text
.length() - firstNonZeroPos
); 
 289         wxString variantType 
= variant
.GetType(); 
 290         bool isPrevLong 
= variantType 
== wxPG_VARIANT_TYPE_LONG
; 
 292         wxLongLong_t value64 
= 0; 
 294         if ( useText
.ToLongLong(&value64
, 10) && 
 295              ( value64 
>= INT_MAX 
|| value64 
<= INT_MIN 
) 
 298             bool doChangeValue 
= isPrevLong
; 
 300             if ( !isPrevLong 
&& variantType 
== wxPG_VARIANT_TYPE_LONGLONG 
) 
 302                 wxLongLong oldValue 
= variant
.GetLongLong(); 
 303                 if ( oldValue
.GetValue() != value64 
) 
 304                     doChangeValue 
= true; 
 309                 wxLongLong 
ll(value64
); 
 315         if ( useText
.ToLong( &value32
, 0 ) ) 
 317             if ( !isPrevLong 
|| variant 
!= value32 
) 
 324     else if ( argFlags 
& wxPG_REPORT_ERROR 
) 
 330 bool wxIntProperty::IntToValue( wxVariant
& variant
, int value
, int WXUNUSED(argFlags
) ) const 
 332     if ( variant
.GetType() != wxPG_VARIANT_TYPE_LONG 
|| variant 
!= (long)value 
) 
 334         variant 
= (long)value
; 
 341 // Common validation code to be called in ValidateValue() 
 344 // Note that 'value' is reference on purpose, so we can write 
 345 // back to it when mode is wxPG_PROPERTY_VALIDATION_SATURATE. 
 348 bool NumericValidation( const wxPGProperty
* property
, 
 350                         wxPGValidationInfo
* pValidationInfo
, 
 352                         const wxString
& strFmt 
) 
 354     T min 
= (T
) wxINT64_MIN
; 
 355     T max 
= (T
) wxINT64_MAX
; 
 360     variant 
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
); 
 361     if ( !variant
.IsNull() ) 
 363         variant
.Convert(&min
); 
 367     variant 
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
); 
 368     if ( !variant
.IsNull() ) 
 370         variant
.Convert(&max
); 
 378             if ( mode 
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE 
) 
 381                 wxString smin 
= wxString::Format(strFmt
, min
); 
 382                 wxString smax 
= wxString::Format(strFmt
, max
); 
 384                     msg 
= wxString::Format( 
 385                                 _("Value must be %s or higher."), 
 388                     msg 
= wxString::Format( 
 389                                 _("Value must be between %s and %s."), 
 390                                 smin
.c_str(), smax
.c_str()); 
 391                 pValidationInfo
->SetFailureMessage(msg
); 
 393             else if ( mode 
== wxPG_PROPERTY_VALIDATION_SATURATE 
) 
 396                 value 
= max 
- (min 
- value
); 
 405             if ( mode 
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE 
) 
 408                 wxString smin 
= wxString::Format(strFmt
, min
); 
 409                 wxString smax 
= wxString::Format(strFmt
, max
); 
 411                     msg 
= wxString::Format( 
 412                                 _("Value must be %s or less."), 
 415                     msg 
= wxString::Format( 
 416                                 _("Value must be between %s and %s."), 
 417                                 smin
.c_str(), smax
.c_str()); 
 418                 pValidationInfo
->SetFailureMessage(msg
); 
 420             else if ( mode 
== wxPG_PROPERTY_VALIDATION_SATURATE 
) 
 423                 value 
= min 
+ (value 
- max
); 
 430 bool wxIntProperty::DoValidation( const wxPGProperty
* property
, 
 432                                   wxPGValidationInfo
* pValidationInfo
, 
 435     return NumericValidation
<wxLongLong_t
>(property
, 
 442 bool wxIntProperty::ValidateValue( wxVariant
& value
, 
 443                                    wxPGValidationInfo
& validationInfo 
) const 
 445     wxLongLong_t ll 
= value
.GetLongLong().GetValue(); 
 446     return DoValidation(this, ll
, &validationInfo
, 
 447                         wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
); 
 450 wxValidator
* wxIntProperty::GetClassValidator() 
 453     WX_PG_DOGETVALIDATOR_ENTRY() 
 455     wxValidator
* validator 
= new wxNumericPropertyValidator( 
 456                                     wxNumericPropertyValidator::Signed
); 
 458     WX_PG_DOGETVALIDATOR_EXIT(validator
) 
 464 wxValidator
* wxIntProperty::DoGetValidator() const 
 466     return GetClassValidator(); 
 469 // ----------------------------------------------------------------------- 
 471 // ----------------------------------------------------------------------- 
 474 #define wxPG_UINT_TEMPLATE_MAX 8 
 476 static const wxChar
* const gs_uintTemplates32
[wxPG_UINT_TEMPLATE_MAX
] = { 
 477     wxT("%lx"),wxT("0x%lx"),wxT("$%lx"), 
 478     wxT("%lX"),wxT("0x%lX"),wxT("$%lX"), 
 479     wxT("%lu"),wxT("%lo") 
 482 static const char* const gs_uintTemplates64
[wxPG_UINT_TEMPLATE_MAX
] = { 
 483     "%" wxLongLongFmtSpec 
"x", 
 484     "0x%" wxLongLongFmtSpec 
"x", 
 485     "$%" wxLongLongFmtSpec 
"x", 
 486     "%" wxLongLongFmtSpec 
"X", 
 487     "0x%" wxLongLongFmtSpec 
"X", 
 488     "$%" wxLongLongFmtSpec 
"X", 
 489     "%" wxLongLongFmtSpec 
"u", 
 490     "%" wxLongLongFmtSpec 
"o" 
 493 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty
,wxPGProperty
, 
 494                                long,unsigned long,TextCtrl
) 
 496 void wxUIntProperty::Init() 
 498     m_base 
= 6; // This is magic number for dec base (must be same as in setattribute) 
 500     m_prefix 
= wxPG_PREFIX_NONE
; 
 503 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
, 
 504     unsigned long value 
) : wxPGProperty(label
,name
) 
 507     SetValue((long)value
); 
 510 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
, 
 511     const wxULongLong
& value 
) : wxPGProperty(label
,name
) 
 514     SetValue(WXVARIANT(value
)); 
 517 wxUIntProperty::~wxUIntProperty() { } 
 519 wxString 
wxUIntProperty::ValueToString( wxVariant
& value
, 
 520                                         int WXUNUSED(argFlags
) ) const 
 522     size_t index 
= m_base 
+ m_prefix
; 
 523     if ( index 
>= wxPG_UINT_TEMPLATE_MAX 
) 
 524         index 
= wxPG_BASE_DEC
; 
 526     if ( value
.GetType() == wxPG_VARIANT_TYPE_LONG 
) 
 528         return wxString::Format(gs_uintTemplates32
[index
], 
 529                                 (unsigned long)value
.GetLong()); 
 532     wxULongLong ull 
= value
.GetULongLong(); 
 534     return wxString::Format(gs_uintTemplates64
[index
], ull
.GetValue()); 
 537 bool wxUIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const 
 539     wxString variantType 
= variant
.GetType(); 
 540     bool isPrevLong 
= variantType 
== wxPG_VARIANT_TYPE_LONG
; 
 549     if ( text
[0] == wxS('$') ) 
 552     wxULongLong_t value64 
= 0; 
 553     wxString s 
= text
.substr(start
, text
.length() - start
); 
 555     if ( s
.ToULongLong(&value64
, (unsigned int)m_realBase
) ) 
 557         if ( value64 
>= LONG_MAX 
) 
 559             bool doChangeValue 
= isPrevLong
; 
 561             if ( !isPrevLong 
&& variantType 
== wxPG_VARIANT_TYPE_ULONGLONG 
) 
 563                 wxULongLong oldValue 
= variant
.GetULongLong(); 
 564                 if ( oldValue
.GetValue() != value64 
) 
 565                     doChangeValue 
= true; 
 570                 variant 
= wxULongLong(value64
); 
 576             unsigned long value32 
= wxLongLong(value64
).GetLo(); 
 577             if ( !isPrevLong 
|| m_value 
!= (long)value32 
) 
 579                 variant 
= (long)value32
; 
 588 bool wxUIntProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const 
 590     if ( variant 
!= (long)number 
) 
 592         variant 
= (long)number
; 
 598 bool wxUIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo 
) const 
 600     wxULongLong_t uul 
= value
.GetULongLong().GetValue(); 
 602     NumericValidation
<wxULongLong_t
>(this, 
 605                                      wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
, 
 609 wxValidator
* wxUIntProperty::DoGetValidator() const 
 612     WX_PG_DOGETVALIDATOR_ENTRY() 
 614     wxValidator
* validator 
= new wxNumericPropertyValidator( 
 615                                     wxNumericPropertyValidator::Unsigned
, 
 618     WX_PG_DOGETVALIDATOR_EXIT(validator
) 
 624 bool wxUIntProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
 626     if ( name 
== wxPG_UINT_BASE 
) 
 628         int val 
= value
.GetLong(); 
 630         m_realBase 
= (wxByte
) val
; 
 631         if ( m_realBase 
> 16 ) 
 635         // Translate logical base to a template array index 
 637         if ( val 
== wxPG_BASE_HEX 
) 
 639         else if ( val 
== wxPG_BASE_DEC 
) 
 641         else if ( val 
== wxPG_BASE_HEXL 
) 
 645     else if ( name 
== wxPG_UINT_PREFIX 
) 
 647         m_prefix 
= (wxByte
) value
.GetLong(); 
 653 // ----------------------------------------------------------------------- 
 655 // ----------------------------------------------------------------------- 
 657 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty
,wxPGProperty
, 
 658                                double,double,TextCtrl
) 
 660 wxFloatProperty::wxFloatProperty( const wxString
& label
, 
 661                                             const wxString
& name
, 
 663     : wxPGProperty(label
,name
) 
 669 wxFloatProperty::~wxFloatProperty() { } 
 671 // This helper method provides standard way for floating point-using 
 672 // properties to convert values to string. 
 673 const wxString
& wxPropertyGrid::DoubleToString(wxString
& target
, 
 677                                                wxString
* precTemplate
) 
 679     if ( precision 
>= 0 ) 
 683             precTemplate 
= &text1
; 
 685         if ( precTemplate
->empty() ) 
 687             *precTemplate 
= wxS("%."); 
 688             *precTemplate 
<< wxString::Format( wxS("%i"), precision 
); 
 689             *precTemplate 
<< wxS('f'); 
 692         target
.Printf( precTemplate
->c_str(), value 
); 
 696         target
.Printf( wxS("%f"), value 
); 
 699     if ( removeZeroes 
&& precision 
!= 0 && !target
.empty() ) 
 701         // Remove excess zeroes (do not remove this code just yet, 
 702         // since sprintf can't do the same consistently across platforms). 
 703         wxString::const_iterator i 
= target
.end() - 1; 
 704         size_t new_len 
= target
.length() - 1; 
 706         for ( ; i 
!= target
.begin(); --i 
) 
 708             if ( *i 
!= wxS('0') ) 
 713         wxChar cur_char 
= *i
; 
 714         if ( cur_char 
!= wxS('.') && cur_char 
!= wxS(',') ) 
 717         if ( new_len 
!= target
.length() ) 
 718             target
.resize(new_len
); 
 721     // Remove sign from zero 
 722     if ( target
.length() >= 2 && target
[0] == wxS('-') ) 
 725         wxString::const_iterator i 
= target
.begin() + 1; 
 727         for ( ; i 
!= target
.end(); i
++ ) 
 729             if ( *i 
!= wxS('0') && *i 
!= wxS('.') && *i 
!= wxS(',') ) 
 737             target
.erase(target
.begin()); 
 743 wxString 
wxFloatProperty::ValueToString( wxVariant
& value
, 
 747     if ( !value
.IsNull() ) 
 749         wxPropertyGrid::DoubleToString(text
, 
 752                                        !(argFlags 
& wxPG_FULL_VALUE
), 
 758 bool wxFloatProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags 
) const 
 769     bool res 
= text
.ToDouble(&value
); 
 772         if ( variant 
!= value 
) 
 778     else if ( argFlags 
& wxPG_REPORT_ERROR 
) 
 784 bool wxFloatProperty::DoValidation( const wxPGProperty
* property
, 
 786                                     wxPGValidationInfo
* pValidationInfo
, 
 789     return NumericValidation
<double>(property
, 
 797 wxFloatProperty::ValidateValue( wxVariant
& value
, 
 798                                 wxPGValidationInfo
& validationInfo 
) const 
 800     double fpv 
= value
.GetDouble(); 
 801     return DoValidation(this, fpv
, &validationInfo
, 
 802                         wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
); 
 805 bool wxFloatProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
 807     if ( name 
== wxPG_FLOAT_PRECISION 
) 
 809         m_precision 
= value
.GetLong(); 
 816 wxFloatProperty::GetClassValidator() 
 819     WX_PG_DOGETVALIDATOR_ENTRY() 
 821     wxValidator
* validator 
= new wxNumericPropertyValidator( 
 822                                     wxNumericPropertyValidator::Float
); 
 824     WX_PG_DOGETVALIDATOR_EXIT(validator
) 
 830 wxValidator
* wxFloatProperty::DoGetValidator() const 
 832     return GetClassValidator(); 
 835 // ----------------------------------------------------------------------- 
 837 // ----------------------------------------------------------------------- 
 839 // We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since 
 840 // there is a custom GetEditorClass. 
 842 IMPLEMENT_DYNAMIC_CLASS(wxBoolProperty
, wxPGProperty
) 
 844 const wxPGEditor
* wxBoolProperty::DoGetEditorClass() const 
 846     // Select correct editor control. 
 847 #if wxPG_INCLUDE_CHECKBOX 
 848     if ( !(m_flags 
& wxPG_PROP_USE_CHECKBOX
) ) 
 849         return wxPGEditor_Choice
; 
 850     return wxPGEditor_CheckBox
; 
 852     return wxPGEditor_Choice
; 
 856 wxBoolProperty::wxBoolProperty( const wxString
& label
, const wxString
& name
, bool value 
) : 
 857     wxPGProperty(label
,name
) 
 859     m_choices
.Assign(wxPGGlobalVars
->m_boolChoices
); 
 861     SetValue(wxPGVariant_Bool(value
)); 
 863     m_flags 
|= wxPG_PROP_USE_DCC
; 
 866 wxBoolProperty::~wxBoolProperty() { } 
 868 wxString 
wxBoolProperty::ValueToString( wxVariant
& value
, 
 871     bool boolValue 
= value
.GetBool(); 
 873     // As a fragment of composite string value, 
 874     // make it a little more readable. 
 875     if ( argFlags 
& wxPG_COMPOSITE_FRAGMENT 
) 
 883             if ( argFlags 
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT 
) 
 884                 return wxEmptyString
; 
 887             if ( wxPGGlobalVars
->m_autoGetTranslation 
) 
 888                 notFmt 
= _("Not %s"); 
 890                 notFmt 
= wxS("Not %s"); 
 892             return wxString::Format(notFmt
.c_str(), m_label
.c_str()); 
 896     if ( !(argFlags 
& wxPG_FULL_VALUE
) ) 
 898         return wxPGGlobalVars
->m_boolChoices
[boolValue
?1:0].GetText(); 
 903     if ( boolValue 
) text 
= wxS("true"); 
 904     else text 
= wxS("false"); 
 909 bool wxBoolProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const 
 911     bool boolValue 
= false; 
 912     if ( text
.CmpNoCase(wxPGGlobalVars
->m_boolChoices
[1].GetText()) == 0 || 
 913          text
.CmpNoCase(wxS("true")) == 0 || 
 914          text
.CmpNoCase(m_label
) == 0 ) 
 923     if ( variant 
!= boolValue 
) 
 925         variant 
= wxPGVariant_Bool(boolValue
); 
 931 bool wxBoolProperty::IntToValue( wxVariant
& variant
, int value
, int ) const 
 933     bool boolValue 
= value 
? true : false; 
 935     if ( variant 
!= boolValue 
) 
 937         variant 
= wxPGVariant_Bool(boolValue
); 
 943 bool wxBoolProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
 945 #if wxPG_INCLUDE_CHECKBOX 
 946     if ( name 
== wxPG_BOOL_USE_CHECKBOX 
) 
 948         if ( value
.GetLong() ) 
 949             m_flags 
|= wxPG_PROP_USE_CHECKBOX
; 
 951             m_flags 
&= ~(wxPG_PROP_USE_CHECKBOX
); 
 955     if ( name 
== wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING 
) 
 957         if ( value
.GetLong() ) 
 958             m_flags 
|= wxPG_PROP_USE_DCC
; 
 960             m_flags 
&= ~(wxPG_PROP_USE_DCC
); 
 966 // ----------------------------------------------------------------------- 
 968 // ----------------------------------------------------------------------- 
 970 IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty
, wxPGProperty
) 
 972 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty
,long,Choice
) 
 974 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
* const* labels
, 
 975     const long* values
, int value 
) : wxPGProperty(label
,name
) 
 981         m_choices
.Add(labels
,values
); 
 983         if ( GetItemCount() ) 
 984             SetValue( (long)value 
); 
 988 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
* const* labels
, 
 989     const long* values
, wxPGChoices
* choicesCache
, int value 
) 
 990     : wxPGProperty(label
,name
) 
 994     wxASSERT( choicesCache 
); 
 996     if ( choicesCache
->IsOk() ) 
 998         m_choices
.Assign( *choicesCache 
); 
 999         m_value 
= wxPGVariant_Zero
; 
1003         m_choices
.Add(labels
,values
); 
1005         if ( GetItemCount() ) 
1006             SetValue( (long)value 
); 
1010 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, 
1011     const wxArrayString
& labels
, const wxArrayInt
& values
, int value 
) 
1012     : wxPGProperty(label
,name
) 
1016     if ( &labels 
&& labels
.size() ) 
1018         m_choices
.Set(labels
, values
); 
1020         if ( GetItemCount() ) 
1021             SetValue( (long)value 
); 
1025 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, 
1026     wxPGChoices
& choices
, int value 
) 
1027     : wxPGProperty(label
,name
) 
1029     m_choices
.Assign( choices 
); 
1031     if ( GetItemCount() ) 
1032         SetValue( (long)value 
); 
1035 int wxEnumProperty::GetIndexForValue( int value 
) const 
1037     if ( !m_choices
.IsOk() ) 
1040     int intVal 
= m_choices
.Index(value
); 
1047 wxEnumProperty::~wxEnumProperty () 
1051 int wxEnumProperty::ms_nextIndex 
= -2; 
1053 void wxEnumProperty::OnSetValue() 
1055     wxString variantType 
= m_value
.GetType(); 
1057     if ( variantType 
== wxPG_VARIANT_TYPE_LONG 
) 
1059         ValueFromInt_( m_value
, m_value
.GetLong(), wxPG_FULL_VALUE 
); 
1061     else if ( variantType 
== wxPG_VARIANT_TYPE_STRING 
) 
1063         ValueFromString_( m_value
, m_value
.GetString(), 0 ); 
1070     if ( ms_nextIndex 
!= -2 ) 
1072         m_index 
= ms_nextIndex
; 
1077 bool wxEnumProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const 
1079     // Make sure string value is in the list, 
1080     // unless property has string as preferred value type 
1081     // To reduce code size, use conversion here as well 
1082     if ( value
.GetType() == wxPG_VARIANT_TYPE_STRING 
&& 
1083          !this->IsKindOf(CLASSINFO(wxEditEnumProperty
)) ) 
1084         return ValueFromString_( value
, value
.GetString(), wxPG_PROPERTY_SPECIFIC 
); 
1089 wxString 
wxEnumProperty::ValueToString( wxVariant
& value
, 
1090                                             int WXUNUSED(argFlags
) ) const 
1092     if ( value
.GetType() == wxPG_VARIANT_TYPE_STRING 
) 
1093         return value
.GetString(); 
1095     int index 
= m_choices
.Index(value
.GetLong()); 
1097         return wxEmptyString
; 
1099     return m_choices
.GetLabel(index
); 
1102 bool wxEnumProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags 
) const 
1104     return ValueFromString_( variant
, text
, argFlags 
); 
1107 bool wxEnumProperty::IntToValue( wxVariant
& variant
, int intVal
, int argFlags 
) const 
1109     return ValueFromInt_( variant
, intVal
, argFlags 
); 
1112 bool wxEnumProperty::ValueFromString_( wxVariant
& value
, const wxString
& text
, int argFlags 
) const 
1117     for ( unsigned int i
=0; i
<m_choices
.GetCount(); i
++ ) 
1119         const wxString
& entryLabel 
= m_choices
.GetLabel(i
); 
1120         if ( text
.CmpNoCase(entryLabel
) == 0 ) 
1123             useValue 
= m_choices
.GetValue(i
); 
1128     bool asText 
= false; 
1130     bool isEdit 
= this->IsKindOf(CLASSINFO(wxEditEnumProperty
)); 
1132     // If text not any of the choices, store as text instead 
1133     // (but only if we are wxEditEnumProperty) 
1134     if ( useIndex 
== -1 && isEdit 
) 
1139     int setAsNextIndex 
= -2; 
1143         setAsNextIndex 
= -1; 
1146     else if ( useIndex 
!= GetIndex() ) 
1148         if ( useIndex 
!= -1 ) 
1150             setAsNextIndex 
= useIndex
; 
1151             value 
= (long)useValue
; 
1155             setAsNextIndex 
= -1; 
1156             value 
= wxPGVariant_MinusOne
; 
1160     if ( setAsNextIndex 
!= -2 ) 
1162         // If wxPG_PROPERTY_SPECIFIC is set, then this is done for 
1163         // validation purposes only, and index must not be changed 
1164         if ( !(argFlags 
& wxPG_PROPERTY_SPECIFIC
) ) 
1165             ms_nextIndex 
= setAsNextIndex
; 
1167         if ( isEdit 
|| setAsNextIndex 
!= -1 ) 
1175 bool wxEnumProperty::ValueFromInt_( wxVariant
& variant
, int intVal
, int argFlags 
) const 
1177     // If wxPG_FULL_VALUE is *not* in argFlags, then intVal is index from combo box. 
1181     if ( argFlags 
& wxPG_FULL_VALUE 
) 
1183         ms_nextIndex 
= GetIndexForValue( intVal 
); 
1187         if ( intVal 
!= GetIndex() ) 
1189             ms_nextIndex 
= intVal
; 
1193     if ( ms_nextIndex 
!= -2 ) 
1195         if ( !(argFlags 
& wxPG_FULL_VALUE
) ) 
1196             intVal 
= m_choices
.GetValue(intVal
); 
1198         variant 
= (long)intVal
; 
1207 wxEnumProperty::OnValidationFailure( wxVariant
& WXUNUSED(pendingValue
) ) 
1213 void wxEnumProperty::SetIndex( int index 
) 
1219 int wxEnumProperty::GetIndex() const 
1221     if ( m_value
.IsNull() ) 
1224     if ( ms_nextIndex 
!= -2 ) 
1225         return ms_nextIndex
; 
1230 // ----------------------------------------------------------------------- 
1231 // wxEditEnumProperty 
1232 // ----------------------------------------------------------------------- 
1234 IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty
, wxPGProperty
) 
1236 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty
,wxString
,ComboBox
) 
1238 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
* const* labels
, 
1239     const long* values
, const wxString
& value 
) 
1240     : wxEnumProperty(label
,name
,labels
,values
,0) 
1245 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
* const* labels
, 
1246     const long* values
, wxPGChoices
* choicesCache
, const wxString
& value 
) 
1247     : wxEnumProperty(label
,name
,labels
,values
,choicesCache
,0) 
1252 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, 
1253     const wxArrayString
& labels
, const wxArrayInt
& values
, const wxString
& value 
) 
1254     : wxEnumProperty(label
,name
,labels
,values
,0) 
1259 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, 
1260     wxPGChoices
& choices
, const wxString
& value 
) 
1261     : wxEnumProperty(label
,name
,choices
,0) 
1266 wxEditEnumProperty::~wxEditEnumProperty() 
1270 // ----------------------------------------------------------------------- 
1272 // ----------------------------------------------------------------------- 
1274 IMPLEMENT_DYNAMIC_CLASS(wxFlagsProperty
,wxPGProperty
) 
1276 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty
,long,TextCtrl
) 
1278 void wxFlagsProperty::Init() 
1280     long value 
= m_value
; 
1283     // Generate children 
1287     unsigned int prevChildCount 
= m_children
.size(); 
1290     if ( prevChildCount 
) 
1292         wxPropertyGridPageState
* state 
= GetParentState(); 
1294         // State safety check (it may be NULL in immediate parent) 
1299             wxPGProperty
* selected 
= state
->GetSelection(); 
1302                 if ( selected
->GetParent() == this ) 
1303                     oldSel 
= selected
->GetIndexInParent(); 
1304                 else if ( selected 
== this ) 
1308         state
->DoClearSelection(); 
1311     // Delete old children 
1312     for ( i
=0; i
<prevChildCount
; i
++ ) 
1313         delete m_children
[i
]; 
1317     // Relay wxPG_BOOL_USE_CHECKBOX and wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING 
1318     // to child bool property controls. 
1319     long attrUseCheckBox 
= GetAttributeAsLong(wxPG_BOOL_USE_CHECKBOX
, 0); 
1320     long attrUseDCC 
= GetAttributeAsLong(wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING
, 
1323     if ( m_choices
.IsOk() ) 
1325         const wxPGChoices
& choices 
= m_choices
; 
1327         for ( i
=0; i
<GetItemCount(); i
++ ) 
1330             child_val 
= ( value 
& choices
.GetValue(i
) )?true:false; 
1332             wxPGProperty
* boolProp
; 
1333             wxString label 
= GetLabel(i
); 
1336             if ( wxPGGlobalVars
->m_autoGetTranslation 
) 
1338                 boolProp 
= new wxBoolProperty( ::wxGetTranslation(label
), label
, child_val 
); 
1343                 boolProp 
= new wxBoolProperty( label
, label
, child_val 
); 
1345             if ( attrUseCheckBox 
) 
1346                 boolProp
->SetAttribute(wxPG_BOOL_USE_CHECKBOX
, 
1349                 boolProp
->SetAttribute(wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING
, 
1351             AddPrivateChild(boolProp
); 
1354         m_oldChoicesData 
= m_choices
.GetDataPtr(); 
1357     m_oldValue 
= m_value
; 
1359     if ( prevChildCount 
) 
1360         SubPropsChanged(oldSel
); 
1363 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
, 
1364     const wxChar
* const* labels
, const long* values
, long value 
) : wxPGProperty(label
,name
) 
1366     m_oldChoicesData 
= NULL
; 
1370         m_choices
.Set(labels
,values
); 
1372         wxASSERT( GetItemCount() ); 
1378         m_value 
= wxPGVariant_Zero
; 
1382 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
, 
1383         const wxArrayString
& labels
, const wxArrayInt
& values
, int value 
) 
1384     : wxPGProperty(label
,name
) 
1386     m_oldChoicesData 
= NULL
; 
1388     if ( &labels 
&& labels
.size() ) 
1390         m_choices
.Set(labels
,values
); 
1392         wxASSERT( GetItemCount() ); 
1394         SetValue( (long)value 
); 
1398         m_value 
= wxPGVariant_Zero
; 
1402 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
, 
1403     wxPGChoices
& choices
, long value 
) 
1404     : wxPGProperty(label
,name
) 
1406     m_oldChoicesData 
= NULL
; 
1408     if ( choices
.IsOk() ) 
1410         m_choices
.Assign(choices
); 
1412         wxASSERT( GetItemCount() ); 
1418         m_value 
= wxPGVariant_Zero
; 
1422 wxFlagsProperty::~wxFlagsProperty() 
1426 void wxFlagsProperty::OnSetValue() 
1428     if ( !m_choices
.IsOk() || !GetItemCount() ) 
1430         m_value 
= wxPGVariant_Zero
; 
1434         long val 
= m_value
.GetLong(); 
1438         // normalize the value (i.e. remove extra flags) 
1440         const wxPGChoices
& choices 
= m_choices
; 
1441         for ( i 
= 0; i 
< GetItemCount(); i
++ ) 
1443             fullFlags 
|= choices
.GetValue(i
); 
1450         // Need to (re)init now? 
1451         if ( GetChildCount() != GetItemCount() || 
1452              m_choices
.GetDataPtr() != m_oldChoicesData 
) 
1458     long newFlags 
= m_value
; 
1460     if ( newFlags 
!= m_oldValue 
) 
1462         // Set child modified states 
1464         const wxPGChoices
& choices 
= m_choices
; 
1465         for ( i 
= 0; i
<GetItemCount(); i
++ ) 
1469             flag 
= choices
.GetValue(i
); 
1471             if ( (newFlags 
& flag
) != (m_oldValue 
& flag
) ) 
1472                 Item(i
)->ChangeFlag( wxPG_PROP_MODIFIED
, true ); 
1475         m_oldValue 
= newFlags
; 
1479 wxString 
wxFlagsProperty::ValueToString( wxVariant
& value
, 
1480                                          int WXUNUSED(argFlags
) ) const 
1484     if ( !m_choices
.IsOk() ) 
1489     const wxPGChoices
& choices 
= m_choices
; 
1491     for ( i 
= 0; i 
< GetItemCount(); i
++ ) 
1494         doAdd 
= ( flags 
& choices
.GetValue(i
) ); 
1498             text 
+= choices
.GetLabel(i
); 
1503     // remove last comma 
1504     if ( text
.Len() > 1 ) 
1505         text
.Truncate ( text
.Len() - 2 ); 
1510 // Translate string into flag tokens 
1511 bool wxFlagsProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const 
1513     if ( !m_choices
.IsOk() ) 
1518     // semicolons are no longer valid delimeters 
1519     WX_PG_TOKENIZER1_BEGIN(text
,wxS(',')) 
1521         if ( !token
.empty() ) 
1523             // Determine which one it is 
1524             long bit 
= IdToBit( token 
); 
1537     WX_PG_TOKENIZER1_END() 
1539     if ( variant 
!= (long)newFlags 
) 
1541         variant 
= (long)newFlags
; 
1548 // Converts string id to a relevant bit. 
1549 long wxFlagsProperty::IdToBit( const wxString
& id 
) const 
1552     for ( i 
= 0; i 
< GetItemCount(); i
++ ) 
1554         if ( id 
== GetLabel(i
) ) 
1556             return m_choices
.GetValue(i
); 
1562 void wxFlagsProperty::RefreshChildren() 
1564     if ( !m_choices
.IsOk() || !GetChildCount() ) return; 
1566     int flags 
= m_value
.GetLong(); 
1568     const wxPGChoices
& choices 
= m_choices
; 
1570     for ( i 
= 0; i 
< GetItemCount(); i
++ ) 
1574         flag 
= choices
.GetValue(i
); 
1576         long subVal 
= flags 
& flag
; 
1577         wxPGProperty
* p 
= Item(i
); 
1579         if ( subVal 
!= (m_oldValue 
& flag
) ) 
1580             p
->ChangeFlag( wxPG_PROP_MODIFIED
, true ); 
1582         p
->SetValue( subVal
?true:false ); 
1588 wxVariant 
wxFlagsProperty::ChildChanged( wxVariant
& thisValue
, 
1590                                          wxVariant
& childValue 
) const 
1592     long oldValue 
= thisValue
.GetLong(); 
1593     long val 
= childValue
.GetLong(); 
1594     unsigned long vi 
= m_choices
.GetValue(childIndex
); 
1597         return (long) (oldValue 
| vi
); 
1599     return (long) (oldValue 
& ~(vi
)); 
1602 bool wxFlagsProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
1604     if ( name 
== wxPG_BOOL_USE_CHECKBOX 
|| 
1605          name 
== wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING 
) 
1607         for ( size_t i
=0; i
<GetChildCount(); i
++ ) 
1609             Item(i
)->SetAttribute(name
, value
); 
1611         // Must return false so that the attribute is stored in 
1612         // flag property's actual property storage 
1618 // ----------------------------------------------------------------------- 
1620 // ----------------------------------------------------------------------- 
1622 IMPLEMENT_DYNAMIC_CLASS(wxDirProperty
, wxLongStringProperty
) 
1624 wxDirProperty::wxDirProperty( const wxString
& name
, const wxString
& label
, const wxString
& value 
) 
1625   : wxLongStringProperty(name
,label
,value
) 
1627     m_flags 
|= wxPG_PROP_NO_ESCAPE
; 
1630 wxDirProperty::~wxDirProperty() { } 
1632 wxValidator
* wxDirProperty::DoGetValidator() const 
1634     return wxFileProperty::GetClassValidator(); 
1637 bool wxDirProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value 
) 
1639     // Update property value from editor, if necessary 
1640     wxSize 
dlg_sz(300,400); 
1642     wxString 
dlgMessage(m_dlgMessage
); 
1643     if ( dlgMessage
.empty() ) 
1644         dlgMessage 
= _("Choose a directory:"); 
1645     wxDirDialog 
dlg( propGrid
, 
1649 #if !wxPG_SMALL_SCREEN 
1650                      propGrid
->GetGoodEditorDialogPosition(this,dlg_sz
), 
1658     if ( dlg
.ShowModal() == wxID_OK 
) 
1660         value 
= dlg
.GetPath(); 
1666 bool wxDirProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
1668     if ( name 
== wxPG_DIR_DIALOG_MESSAGE 
) 
1670         m_dlgMessage 
= value
.GetString(); 
1676 // ----------------------------------------------------------------------- 
1677 // wxPGFileDialogAdapter 
1678 // ----------------------------------------------------------------------- 
1680 bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property 
) 
1682     wxFileProperty
* fileProp 
= NULL
; 
1686     if ( property
->IsKindOf(CLASSINFO(wxFileProperty
)) ) 
1688         fileProp 
= ((wxFileProperty
*)property
); 
1689         wxFileName filename 
= fileProp
->GetValue().GetString(); 
1690         path 
= filename
.GetPath(); 
1691         indFilter 
= fileProp
->m_indFilter
; 
1693         if ( path
.empty() && !fileProp
->m_basePath
.empty() ) 
1694             path 
= fileProp
->m_basePath
; 
1698         wxFileName 
fn(property
->GetValue().GetString()); 
1699         path 
= fn
.GetPath(); 
1702     wxFileDialog 
dlg( propGrid
->GetPanel(), 
1703                       property
->GetAttribute(wxS("DialogTitle"), _("Choose a file")), 
1704                       property
->GetAttribute(wxS("InitialPath"), path
), 
1706                       property
->GetAttribute(wxPG_FILE_WILDCARD
, wxALL_FILES
), 
1707                       property
->GetAttributeAsLong(wxPG_FILE_DIALOG_STYLE
, 0), 
1708                       wxDefaultPosition 
); 
1710     if ( indFilter 
>= 0 ) 
1711         dlg
.SetFilterIndex( indFilter 
); 
1713     if ( dlg
.ShowModal() == wxID_OK 
) 
1716             fileProp
->m_indFilter 
= dlg
.GetFilterIndex(); 
1717         SetValue( dlg
.GetPath() ); 
1723 // ----------------------------------------------------------------------- 
1725 // ----------------------------------------------------------------------- 
1727 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty
,wxPGProperty
, 
1728                                wxString
,const wxString
&,TextCtrlAndButton
) 
1730 wxFileProperty::wxFileProperty( const wxString
& label
, const wxString
& name
, 
1731     const wxString
& value 
) : wxPGProperty(label
,name
) 
1733     m_flags 
|= wxPG_PROP_SHOW_FULL_FILENAME
; 
1735     SetAttribute( wxPG_FILE_WILDCARD
, wxALL_FILES
); 
1740 wxFileProperty::~wxFileProperty() {} 
1742 wxValidator
* wxFileProperty::GetClassValidator() 
1744 #if wxUSE_VALIDATORS 
1745     WX_PG_DOGETVALIDATOR_ENTRY() 
1747     // Atleast wxPython 2.6.2.1 required that the string argument is given 
1749     wxTextValidator
* validator 
= new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST
,&v
); 
1751     wxArrayString exChars
; 
1752     exChars
.Add(wxS("?")); 
1753     exChars
.Add(wxS("*")); 
1754     exChars
.Add(wxS("|")); 
1755     exChars
.Add(wxS("<")); 
1756     exChars
.Add(wxS(">")); 
1757     exChars
.Add(wxS("\"")); 
1759     validator
->SetExcludes(exChars
); 
1761     WX_PG_DOGETVALIDATOR_EXIT(validator
) 
1767 wxValidator
* wxFileProperty::DoGetValidator() const 
1769     return GetClassValidator(); 
1772 void wxFileProperty::OnSetValue() 
1774     const wxString
& fnstr 
= m_value
.GetString(); 
1776     wxFileName filename 
= fnstr
; 
1778     if ( !filename
.HasName() ) 
1780         m_value 
= wxPGVariant_EmptyString
; 
1783     // Find index for extension. 
1784     if ( m_indFilter 
< 0 && !fnstr
.empty() ) 
1786         wxString ext 
= filename
.GetExt(); 
1789         size_t len 
= m_wildcard
.length(); 
1791         pos 
= m_wildcard
.find(wxS("|"), pos
); 
1792         while ( pos 
!= wxString::npos 
&& pos 
< (len
-3) ) 
1794             size_t ext_begin 
= pos 
+ 3; 
1796             pos 
= m_wildcard
.find(wxS("|"), ext_begin
); 
1797             if ( pos 
== wxString::npos 
) 
1799             wxString found_ext 
= m_wildcard
.substr(ext_begin
, pos
-ext_begin
); 
1801             if ( !found_ext
.empty() ) 
1803                 if ( found_ext
[0] == wxS('*') ) 
1805                     m_indFilter 
= curind
; 
1808                 if ( ext
.CmpNoCase(found_ext
) == 0 ) 
1810                     m_indFilter 
= curind
; 
1816                 pos 
= m_wildcard
.find(wxS("|"), pos
+1); 
1823 wxFileName 
wxFileProperty::GetFileName() const 
1825     wxFileName filename
; 
1827     if ( !m_value
.IsNull() ) 
1828         filename 
= m_value
.GetString(); 
1833 wxString 
wxFileProperty::ValueToString( wxVariant
& value
, 
1834                                         int argFlags 
) const 
1836     wxFileName filename 
= value
.GetString(); 
1838     if ( !filename
.HasName() ) 
1839         return wxEmptyString
; 
1841     wxString fullName 
= filename
.GetFullName(); 
1842     if ( fullName
.empty() ) 
1843         return wxEmptyString
; 
1845     if ( argFlags 
& wxPG_FULL_VALUE 
) 
1847         return filename
.GetFullPath(); 
1849     else if ( m_flags 
& wxPG_PROP_SHOW_FULL_FILENAME 
) 
1851         if ( !m_basePath
.empty() ) 
1853             wxFileName 
fn2(filename
); 
1854             fn2
.MakeRelativeTo(m_basePath
); 
1855             return fn2
.GetFullPath(); 
1857         return filename
.GetFullPath(); 
1860     return filename
.GetFullName(); 
1863 wxPGEditorDialogAdapter
* wxFileProperty::GetEditorDialog() const 
1865     return new wxPGFileDialogAdapter(); 
1868 bool wxFileProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags 
) const 
1870     wxFileName filename 
= variant
.GetString(); 
1872     if ( (m_flags 
& wxPG_PROP_SHOW_FULL_FILENAME
) || (argFlags 
& wxPG_FULL_VALUE
) ) 
1874         if ( filename 
!= text 
) 
1882         if ( filename
.GetFullName() != text 
) 
1884             wxFileName fn 
= filename
; 
1885             fn
.SetFullName(text
); 
1886             variant 
= fn
.GetFullPath(); 
1894 bool wxFileProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
1896     // Return false on some occasions to make sure those attribs will get 
1897     // stored in m_attributes. 
1898     if ( name 
== wxPG_FILE_SHOW_FULL_PATH 
) 
1900         if ( value
.GetLong() ) 
1901             m_flags 
|= wxPG_PROP_SHOW_FULL_FILENAME
; 
1903             m_flags 
&= ~(wxPG_PROP_SHOW_FULL_FILENAME
); 
1906     else if ( name 
== wxPG_FILE_WILDCARD 
) 
1908         m_wildcard 
= value
.GetString(); 
1910     else if ( name 
== wxPG_FILE_SHOW_RELATIVE_PATH 
) 
1912         m_basePath 
= value
.GetString(); 
1914         // Make sure wxPG_FILE_SHOW_FULL_PATH is also set 
1915         m_flags 
|= wxPG_PROP_SHOW_FULL_FILENAME
; 
1917     else if ( name 
== wxPG_FILE_INITIAL_PATH 
) 
1919         m_initialPath 
= value
.GetString(); 
1922     else if ( name 
== wxPG_FILE_DIALOG_TITLE 
) 
1924         m_dlgTitle 
= value
.GetString(); 
1930 // ----------------------------------------------------------------------- 
1931 // wxPGLongStringDialogAdapter 
1932 // ----------------------------------------------------------------------- 
1934 bool wxPGLongStringDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property 
) 
1936     wxString val1 
= property
->GetValueAsString(0); 
1937     wxString val_orig 
= val1
; 
1940     if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) ) 
1941         wxPropertyGrid::ExpandEscapeSequences(value
, val1
); 
1943         value 
= wxString(val1
); 
1945     // Run editor dialog. 
1946     if ( wxLongStringProperty::DisplayEditorDialog(property
, propGrid
, value
) ) 
1948         if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) ) 
1949             wxPropertyGrid::CreateEscapeSequences(val1
,value
); 
1953         if ( val1 
!= val_orig 
) 
1962 // ----------------------------------------------------------------------- 
1963 // wxLongStringProperty 
1964 // ----------------------------------------------------------------------- 
1966 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty
,wxPGProperty
, 
1967                                wxString
,const wxString
&,TextCtrlAndButton
) 
1969 wxLongStringProperty::wxLongStringProperty( const wxString
& label
, const wxString
& name
, 
1970     const wxString
& value 
) : wxPGProperty(label
,name
) 
1975 wxLongStringProperty::~wxLongStringProperty() {} 
1977 wxString 
wxLongStringProperty::ValueToString( wxVariant
& value
, 
1978                                               int WXUNUSED(argFlags
) ) const 
1983 bool wxLongStringProperty::OnEvent( wxPropertyGrid
* propGrid
, wxWindow
* WXUNUSED(primary
), 
1986     if ( propGrid
->IsMainButtonEvent(event
) ) 
1989         wxVariant useValue 
= propGrid
->GetUncommittedPropertyValue(); 
1991         wxString val1 
= useValue
.GetString(); 
1992         wxString val_orig 
= val1
; 
1995         if ( !(m_flags 
& wxPG_PROP_NO_ESCAPE
) ) 
1996             wxPropertyGrid::ExpandEscapeSequences(value
,val1
); 
1998             value 
= wxString(val1
); 
2000         // Run editor dialog. 
2001         if ( OnButtonClick(propGrid
,value
) ) 
2003             if ( !(m_flags 
& wxPG_PROP_NO_ESCAPE
) ) 
2004                 wxPropertyGrid::CreateEscapeSequences(val1
,value
); 
2008             if ( val1 
!= val_orig 
) 
2010                 SetValueInEvent( val1 
); 
2018 bool wxLongStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value 
) 
2020     return DisplayEditorDialog(this, propGrid
, value
); 
2023 bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty
* prop
, wxPropertyGrid
* propGrid
, wxString
& value 
) 
2026     // launch editor dialog 
2027     wxDialog
* dlg 
= new wxDialog(propGrid
,-1,prop
->GetLabel(),wxDefaultPosition
,wxDefaultSize
, 
2028                                  wxDEFAULT_DIALOG_STYLE
|wxRESIZE_BORDER
|wxCLIP_CHILDREN
); 
2030     dlg
->SetFont(propGrid
->GetFont()); // To allow entering chars of the same set as the propGrid 
2032     // Multi-line text editor dialog. 
2033 #if !wxPG_SMALL_SCREEN 
2034     const int spacing 
= 8; 
2036     const int spacing 
= 4; 
2038     wxBoxSizer
* topsizer 
= new wxBoxSizer( wxVERTICAL 
); 
2039     wxBoxSizer
* rowsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
2040     wxTextCtrl
* ed 
= new wxTextCtrl(dlg
,11,value
, 
2041         wxDefaultPosition
,wxDefaultSize
,wxTE_MULTILINE
); 
2043     rowsizer
->Add( ed
, 1, wxEXPAND
|wxALL
, spacing 
); 
2044     topsizer
->Add( rowsizer
, 1, wxEXPAND
, 0 ); 
2046     wxStdDialogButtonSizer
* buttonSizer 
= new wxStdDialogButtonSizer(); 
2047     buttonSizer
->AddButton(new wxButton(dlg
, wxID_OK
)); 
2048     buttonSizer
->AddButton(new wxButton(dlg
, wxID_CANCEL
)); 
2049     buttonSizer
->Realize(); 
2050     topsizer
->Add( buttonSizer
, 0, 
2051                    wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxBOTTOM
|wxRIGHT
, 
2054     dlg
->SetSizer( topsizer 
); 
2055     topsizer
->SetSizeHints( dlg 
); 
2057 #if !wxPG_SMALL_SCREEN 
2058     dlg
->SetSize(400,300); 
2060     dlg
->Move( propGrid
->GetGoodEditorDialogPosition(prop
,dlg
->GetSize()) ); 
2063     int res 
= dlg
->ShowModal(); 
2065     if ( res 
== wxID_OK 
) 
2067         value 
= ed
->GetValue(); 
2075 bool wxLongStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const 
2077     if ( variant 
!= text 
) 
2085 #if wxUSE_EDITABLELISTBOX 
2087 // ----------------------------------------------------------------------- 
2088 // wxPGArrayEditorDialog 
2089 // ----------------------------------------------------------------------- 
2091 BEGIN_EVENT_TABLE(wxPGArrayEditorDialog
, wxDialog
) 
2092     EVT_IDLE(wxPGArrayEditorDialog::OnIdle
) 
2095 IMPLEMENT_ABSTRACT_CLASS(wxPGArrayEditorDialog
, wxDialog
) 
2097 #include "wx/editlbox.h" 
2098 #include "wx/listctrl.h" 
2100 // ----------------------------------------------------------------------- 
2102 void wxPGArrayEditorDialog::OnIdle(wxIdleEvent
& event
) 
2104     // Repair focus - wxEditableListBox has bitmap buttons, which 
2105     // get focus, and lose focus (into the oblivion) when they 
2106     // become disabled due to change in control state. 
2108     wxWindow
* lastFocused 
= m_lastFocused
; 
2109     wxWindow
* focus 
= ::wxWindow::FindFocus(); 
2111     // If last focused control became disabled, set focus back to 
2112     // wxEditableListBox 
2113     if ( lastFocused 
&& focus 
!= lastFocused 
&& 
2114          lastFocused
->GetParent() == m_elbSubPanel 
&& 
2115          !lastFocused
->IsEnabled() ) 
2117         m_elb
->GetListCtrl()->SetFocus(); 
2120     m_lastFocused 
= focus
; 
2125 // ----------------------------------------------------------------------- 
2127 wxPGArrayEditorDialog::wxPGArrayEditorDialog() 
2133 // ----------------------------------------------------------------------- 
2135 void wxPGArrayEditorDialog::Init() 
2137     m_lastFocused 
= NULL
; 
2138     m_hasCustomNewAction 
= false; 
2139     m_itemPendingAtIndex 
= -1; 
2142 // ----------------------------------------------------------------------- 
2144 wxPGArrayEditorDialog::wxPGArrayEditorDialog( wxWindow 
*parent
, 
2145                                           const wxString
& message
, 
2146                                           const wxString
& caption
, 
2153     Create(parent
,message
,caption
,style
,pos
,sz
); 
2156 // ----------------------------------------------------------------------- 
2158 bool wxPGArrayEditorDialog::Create( wxWindow 
*parent
, 
2159                                   const wxString
& message
, 
2160                                   const wxString
& caption
, 
2165     // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION 
2166     // FIXME: This should be only a temporary fix. 
2169     int useStyle 
= wxCAPTION
; 
2171     int useStyle 
= style
; 
2174     bool res 
= wxDialog::Create(parent
, wxID_ANY
, caption
, pos
, sz
, useStyle
); 
2176     SetFont(parent
->GetFont()); // To allow entering chars of the same set as the propGrid 
2178 #if !wxPG_SMALL_SCREEN 
2179     const int spacing 
= 4; 
2181     const int spacing 
= 3; 
2186     wxBoxSizer
* topsizer 
= new wxBoxSizer( wxVERTICAL 
); 
2189     if ( !message
.empty() ) 
2190         topsizer
->Add( new wxStaticText(this,-1,message
), 
2191             0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing 
); 
2193     m_elb 
= new wxEditableListBox(this, wxID_ANY
, message
, 
2200     // Populate the list box 
2202     for ( unsigned int i
=0; i
<ArrayGetCount(); i
++ ) 
2203         arr
.push_back(ArrayGet(i
)); 
2204     m_elb
->SetStrings(arr
); 
2206     // Connect event handlers 
2208     wxListCtrl
* lc 
= m_elb
->GetListCtrl(); 
2210     but 
= m_elb
->GetNewButton(); 
2211     m_elbSubPanel 
= but
->GetParent(); 
2212     but
->Connect(but
->GetId(), wxEVT_COMMAND_BUTTON_CLICKED
, 
2213         wxCommandEventHandler(wxPGArrayEditorDialog::OnAddClick
), 
2216     but 
= m_elb
->GetDelButton(); 
2217     but
->Connect(but
->GetId(), wxEVT_COMMAND_BUTTON_CLICKED
, 
2218         wxCommandEventHandler(wxPGArrayEditorDialog::OnDeleteClick
), 
2221     but 
= m_elb
->GetUpButton(); 
2222     but
->Connect(but
->GetId(), wxEVT_COMMAND_BUTTON_CLICKED
, 
2223         wxCommandEventHandler(wxPGArrayEditorDialog::OnUpClick
), 
2226     but 
= m_elb
->GetDownButton(); 
2227     but
->Connect(but
->GetId(), wxEVT_COMMAND_BUTTON_CLICKED
, 
2228         wxCommandEventHandler(wxPGArrayEditorDialog::OnDownClick
), 
2231     lc
->Connect(lc
->GetId(), wxEVT_COMMAND_LIST_END_LABEL_EDIT
, 
2232         wxListEventHandler(wxPGArrayEditorDialog::OnEndLabelEdit
), 
2235     topsizer
->Add( m_elb
, 1, wxEXPAND
, spacing 
); 
2237     // Standard dialog buttons 
2238     wxStdDialogButtonSizer
* buttonSizer 
= new wxStdDialogButtonSizer(); 
2239     buttonSizer
->AddButton(new wxButton(this, wxID_OK
)); 
2240     buttonSizer
->AddButton(new wxButton(this, wxID_CANCEL
)); 
2241     buttonSizer
->Realize(); 
2242     topsizer
->Add( buttonSizer
, 0, 
2243                    wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, 
2248     SetSizer( topsizer 
); 
2249     topsizer
->SetSizeHints( this ); 
2251 #if !wxPG_SMALL_SCREEN 
2252     if ( sz
.x 
== wxDefaultSize
.x 
&& 
2253          sz
.y 
== wxDefaultSize
.y 
) 
2254         SetSize( wxSize(275,360) ); 
2262 // ----------------------------------------------------------------------- 
2264 int wxPGArrayEditorDialog::GetSelection() const 
2266     wxListCtrl
* lc 
= m_elb
->GetListCtrl(); 
2268     int index 
= lc
->GetNextItem(-1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
); 
2275 // ----------------------------------------------------------------------- 
2277 void wxPGArrayEditorDialog::OnAddClick(wxCommandEvent
& event
) 
2279     wxListCtrl
* lc 
= m_elb
->GetListCtrl(); 
2280     int newItemIndex 
= lc
->GetItemCount() - 1; 
2282     if ( m_hasCustomNewAction 
) 
2285         if ( OnCustomNewAction(&str
) ) 
2287             if ( ArrayInsert(str
, newItemIndex
) ) 
2289                 lc
->InsertItem(newItemIndex
, str
); 
2294         // Do *not* skip the event! We do not want the wxEditableListBox 
2299         m_itemPendingAtIndex 
= newItemIndex
; 
2305 // ----------------------------------------------------------------------- 
2307 void wxPGArrayEditorDialog::OnDeleteClick(wxCommandEvent
& event
) 
2309     int index 
= GetSelection(); 
2312         ArrayRemoveAt( index 
); 
2319 // ----------------------------------------------------------------------- 
2321 void wxPGArrayEditorDialog::OnUpClick(wxCommandEvent
& event
) 
2323     int index 
= GetSelection(); 
2326         ArraySwap(index
-1,index
); 
2333 // ----------------------------------------------------------------------- 
2335 void wxPGArrayEditorDialog::OnDownClick(wxCommandEvent
& event
) 
2337     wxListCtrl
* lc 
= m_elb
->GetListCtrl(); 
2338     int index 
= GetSelection(); 
2339     int lastStringIndex 
= lc
->GetItemCount() - 1; 
2340     if ( index 
>= 0 && index 
< lastStringIndex 
) 
2342         ArraySwap(index
, index
+1); 
2349 // ----------------------------------------------------------------------- 
2351 void wxPGArrayEditorDialog::OnEndLabelEdit(wxListEvent
& event
) 
2353     wxString str 
= event
.GetLabel(); 
2355     if ( m_itemPendingAtIndex 
>= 0 ) 
2358         if ( ArrayInsert(str
, m_itemPendingAtIndex
) ) 
2364             // Editable list box doesn't really respect Veto(), but 
2365             // it recognizes if no text was added, so we simulate 
2367             event
.m_item
.SetText(wxEmptyString
); 
2368             m_elb
->GetListCtrl()->SetItemText(m_itemPendingAtIndex
, 
2376         // Change an existing item 
2377         int index 
= GetSelection(); 
2378         wxASSERT( index 
!= wxNOT_FOUND 
); 
2379         if ( ArraySet(index
, str
) ) 
2388 #endif // wxUSE_EDITABLELISTBOX 
2390 // ----------------------------------------------------------------------- 
2391 // wxPGArrayStringEditorDialog 
2392 // ----------------------------------------------------------------------- 
2394 IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog
, wxPGArrayEditorDialog
) 
2396 BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog
, wxPGArrayEditorDialog
) 
2399 // ----------------------------------------------------------------------- 
2401 wxString 
wxPGArrayStringEditorDialog::ArrayGet( size_t index 
) 
2403     return m_array
[index
]; 
2406 size_t wxPGArrayStringEditorDialog::ArrayGetCount() 
2408     return m_array
.size(); 
2411 bool wxPGArrayStringEditorDialog::ArrayInsert( const wxString
& str
, int index 
) 
2416         m_array
.Insert(str
,index
); 
2420 bool wxPGArrayStringEditorDialog::ArraySet( size_t index
, const wxString
& str 
) 
2422     m_array
[index
] = str
; 
2426 void wxPGArrayStringEditorDialog::ArrayRemoveAt( int index 
) 
2428     m_array
.RemoveAt(index
); 
2431 void wxPGArrayStringEditorDialog::ArraySwap( size_t first
, size_t second 
) 
2433     wxString old_str 
= m_array
[first
]; 
2434     wxString new_str 
= m_array
[second
]; 
2435     m_array
[first
] = new_str
; 
2436     m_array
[second
] = old_str
; 
2439 wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog() 
2440     : wxPGArrayEditorDialog() 
2445 void wxPGArrayStringEditorDialog::Init() 
2447     m_pCallingClass 
= NULL
; 
2451 wxPGArrayStringEditorDialog::OnCustomNewAction(wxString
* resString
) 
2453     return m_pCallingClass
->OnCustomStringEdit(m_parent
, *resString
); 
2456 // ----------------------------------------------------------------------- 
2457 // wxArrayStringProperty 
2458 // ----------------------------------------------------------------------- 
2460 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty
,  // Property name 
2461                                wxPGProperty
,  // Property we inherit from 
2462                                wxArrayString
,  // Value type name 
2463                                const wxArrayString
&,  // Value type, as given in constructor 
2464                                TextCtrlAndButton
)  // Initial editor 
2466 wxArrayStringProperty::wxArrayStringProperty( const wxString
& label
, 
2467                                                         const wxString
& name
, 
2468                                                         const wxArrayString
& array 
) 
2469     : wxPGProperty(label
,name
) 
2475 wxArrayStringProperty::~wxArrayStringProperty() { } 
2477 void wxArrayStringProperty::OnSetValue() 
2479     GenerateValueAsString(); 
2483 wxArrayStringProperty::ConvertArrayToString(const wxArrayString
& arr
, 
2485                                             const wxUniChar
& delimiter
) const 
2487     if ( delimiter 
== '"' || delimiter 
== '\'' ) 
2490         ArrayStringToString(*pString
, 
2493                             Escape 
| QuoteStrings
); 
2497         // Regular delimiter 
2498         ArrayStringToString(*pString
, 
2505 wxString 
wxArrayStringProperty::ValueToString( wxVariant
& WXUNUSED(value
), 
2506                                                int argFlags 
) const 
2509     // If this is called from GetValueAsString(), return cached string 
2510     if ( argFlags 
& wxPG_VALUE_IS_CURRENT 
) 
2515     wxArrayString arr 
= m_value
.GetArrayString(); 
2517     ConvertArrayToString(arr
, &s
, m_delimiter
); 
2521 // Converts wxArrayString to a string separated by delimeters and spaces. 
2522 // preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash 
2525 wxArrayStringProperty::ArrayStringToString( wxString
& dst
, 
2526                                             const wxArrayString
& src
, 
2527                                             wxUniChar delimiter
, int flags 
) 
2533     unsigned int itemCount 
= src
.size(); 
2537     if ( flags 
& Escape 
) 
2540         pdr 
= wxS("\\") + static_cast<wchar_t>(delimiter
); 
2544         dst
.append( preas 
); 
2546     wxString 
delimStr(delimiter
); 
2548     for ( i 
= 0; i 
< itemCount
; i
++ ) 
2550         wxString 
str( src
.Item(i
) ); 
2552         // Do some character conversion. 
2553         // Converts \ to \\ and $delimiter to \$delimiter 
2554         // Useful when quoting. 
2555         if ( flags 
& Escape 
) 
2557             str
.Replace( wxS("\\"), wxS("\\\\"), true ); 
2559                 str
.Replace( preas
, pdr
, true ); 
2564         if ( i 
< (itemCount
-1) ) 
2566             dst
.append( delimStr 
); 
2567             dst
.append( wxS(" ") ); 
2568             dst
.append( preas 
); 
2570         else if ( flags 
& QuoteStrings 
) 
2571             dst
.append( delimStr 
); 
2575 void wxArrayStringProperty::GenerateValueAsString() 
2577     wxArrayString arr 
= m_value
.GetArrayString(); 
2578     ConvertArrayToString(arr
, &m_display
, m_delimiter
); 
2581 // Default implementation doesn't do anything. 
2582 bool wxArrayStringProperty::OnCustomStringEdit( wxWindow
*, wxString
& ) 
2587 wxPGArrayEditorDialog
* wxArrayStringProperty::CreateEditorDialog() 
2589     return new wxPGArrayStringEditorDialog(); 
2592 bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
, 
2593                                            wxWindow
* WXUNUSED(primaryCtrl
), 
2597     wxVariant useValue 
= propGrid
->GetUncommittedPropertyValue(); 
2599     if ( !propGrid
->EditorValidate() ) 
2602     // Create editor dialog. 
2603     wxPGArrayEditorDialog
* dlg 
= CreateEditorDialog(); 
2604 #if wxUSE_VALIDATORS 
2605     wxValidator
* validator 
= GetValidator(); 
2606     wxPGInDialogValidator dialogValidator
; 
2609     wxPGArrayStringEditorDialog
* strEdDlg 
= wxDynamicCast(dlg
, wxPGArrayStringEditorDialog
); 
2612         strEdDlg
->SetCustomButton(cbt
, this); 
2614     dlg
->SetDialogValue( useValue 
); 
2615     dlg
->Create(propGrid
, wxEmptyString
, m_label
); 
2617 #if !wxPG_SMALL_SCREEN 
2618     dlg
->Move( propGrid
->GetGoodEditorDialogPosition(this,dlg
->GetSize()) ); 
2627         int res 
= dlg
->ShowModal(); 
2629         if ( res 
== wxID_OK 
&& dlg
->IsModified() ) 
2631             wxVariant value 
= dlg
->GetDialogValue(); 
2632             if ( !value
.IsNull() ) 
2634                 wxArrayString actualValue 
= value
.GetArrayString(); 
2636                 ConvertArrayToString(actualValue
, &tempStr
, m_delimiter
); 
2637             #if wxUSE_VALIDATORS 
2638                 if ( dialogValidator
.DoValidate(propGrid
, validator
, 
2642                     SetValueInEvent( actualValue 
); 
2659 bool wxArrayStringProperty::OnEvent( wxPropertyGrid
* propGrid
, 
2663     if ( propGrid
->IsMainButtonEvent(event
) ) 
2664         return OnButtonClick(propGrid
,primary
,(const wxChar
*) NULL
); 
2668 bool wxArrayStringProperty::StringToValue( wxVariant
& variant
, 
2669                                            const wxString
& text
, int ) const 
2673     if ( m_delimiter 
== '"' || m_delimiter 
== '\'' ) 
2676         WX_PG_TOKENIZER2_BEGIN(text
, m_delimiter
) 
2678             // Need to replace backslashes with empty characters 
2679             // (opposite what is done in ConvertArrayToString()). 
2680             token
.Replace ( wxS("\\\\"), wxS("\\"), true ); 
2684         WX_PG_TOKENIZER2_END() 
2688         // Regular delimiter 
2689         WX_PG_TOKENIZER1_BEGIN(text
, m_delimiter
) 
2691         WX_PG_TOKENIZER1_END() 
2699 bool wxArrayStringProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value 
) 
2701     if ( name 
== wxPG_ARRAY_DELIMITER 
) 
2703         m_delimiter 
= value
.GetChar(); 
2704         GenerateValueAsString(); 
2710 // ----------------------------------------------------------------------- 
2711 // wxPGInDialogValidator 
2712 // ----------------------------------------------------------------------- 
2714 #if wxUSE_VALIDATORS 
2715 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* propGrid
, 
2716                                         wxValidator
* validator
, 
2717                                         const wxString
& value 
) 
2722     wxTextCtrl
* tc 
= m_textCtrl
; 
2727             tc 
= new wxTextCtrl( propGrid
, wxPG_SUBID_TEMP1
, wxEmptyString
, 
2728                                  wxPoint(30000,30000)); 
2735     tc
->SetValue(value
); 
2737     validator
->SetWindow(tc
); 
2738     bool res 
= validator
->Validate(propGrid
); 
2743 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* WXUNUSED(propGrid
), 
2744                                         wxValidator
* WXUNUSED(validator
), 
2745                                         const wxString
& WXUNUSED(value
) ) 
2751 // ----------------------------------------------------------------------- 
2753 #endif  // wxUSE_PROPGRID