1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/props.cpp
3 // Purpose: Basic Property 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/dcclient.h"
32 #include "wx/dcmemory.h"
33 #include "wx/button.h"
36 #include "wx/cursor.h"
37 #include "wx/dialog.h"
38 #include "wx/settings.h"
39 #include "wx/msgdlg.h"
40 #include "wx/choice.h"
41 #include "wx/stattext.h"
42 #include "wx/scrolwin.h"
43 #include "wx/dirdlg.h"
44 #include "wx/combobox.h"
45 #include "wx/layout.h"
47 #include "wx/textdlg.h"
48 #include "wx/filedlg.h"
52 #include <wx/filename.h>
54 #include <wx/propgrid/propgrid.h>
56 #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc.
59 // -----------------------------------------------------------------------
61 // -----------------------------------------------------------------------
63 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty
,wxPGProperty
,
64 wxString
,const wxString
&,TextCtrl
)
66 wxStringProperty::wxStringProperty( const wxString
& label
,
68 const wxString
& value
)
69 : wxPGProperty(label
,name
)
74 void wxStringProperty::OnSetValue()
76 if ( !m_value
.IsNull() && m_value
.GetString() == wxS("<composed>") )
77 SetFlag(wxPG_PROP_COMPOSED_VALUE
);
79 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
82 GenerateComposedValue(s
, 0);
87 wxStringProperty::~wxStringProperty() { }
89 wxString
wxStringProperty::GetValueAsString( int argFlags
) const
91 wxString s
= m_value
.GetString();
93 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
95 // Value stored in m_value is non-editable, non-full value
96 if ( (argFlags
& wxPG_FULL_VALUE
) || (argFlags
& wxPG_EDITABLE_VALUE
) )
97 GenerateComposedValue(s
, argFlags
);
102 // If string is password and value is for visual purposes,
103 // then return asterisks instead the actual string.
104 if ( (m_flags
& wxPG_PROP_PASSWORD
) && !(argFlags
& (wxPG_FULL_VALUE
|wxPG_EDITABLE_VALUE
)) )
105 return wxString(wxChar('*'), s
.Length());
110 bool wxStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
112 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
113 return wxPGProperty::StringToValue(variant
, text
, argFlags
);
115 if ( m_value
.GetString() != text
)
124 bool wxStringProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
126 if ( name
== wxPG_STRING_PASSWORD
)
128 m_flags
&= ~(wxPG_PROP_PASSWORD
);
129 if ( wxPGVariantToInt(value
) ) m_flags
|= wxPG_PROP_PASSWORD
;
136 // -----------------------------------------------------------------------
138 // -----------------------------------------------------------------------
140 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty
,wxPGProperty
,
143 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
,
144 long value
) : wxPGProperty(label
,name
)
149 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
,
150 const wxLongLong
& value
) : wxPGProperty(label
,name
)
152 SetValue(WXVARIANT(value
));
155 wxIntProperty::~wxIntProperty() { }
157 wxString
wxIntProperty::GetValueAsString( int ) const
159 if ( m_value
.GetType() == wxPG_VARIANT_TYPE_LONG
)
161 return wxString::Format(wxS("%li"),m_value
.GetLong());
163 else if ( m_value
.GetType() == wxLongLong_VariantType
)
167 return ll
.ToString();
170 return wxEmptyString
;
173 bool wxIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
178 if ( text
.length() == 0 )
184 // We know it is a number, but let's still check
186 if ( text
.IsNumber() )
188 // Remove leading zeroes, so that the number is not interpreted as octal
189 wxString::const_iterator i
= text
.begin();
190 wxString::const_iterator iMax
= text
.end() - 1; // Let's allow one, last zero though
192 int firstNonZeroPos
= 0;
194 for ( ; i
!= iMax
; i
++ )
197 if ( c
!= wxS('0') && c
!= wxS(' ') )
202 wxString useText
= text
.substr(firstNonZeroPos
, text
.length() - firstNonZeroPos
);
204 wxString variantType
= variant
.GetType();
205 bool isPrevLong
= variantType
== wxPG_VARIANT_TYPE_LONG
;
207 wxLongLong_t value64
= 0;
209 if ( useText
.ToLongLong(&value64
, 10) &&
210 ( value64
>= INT_MAX
|| value64
<= INT_MIN
)
213 bool doChangeValue
= isPrevLong
;
215 if ( !isPrevLong
&& variantType
== wxLongLong_VariantType
)
219 if ( oldValue
.GetValue() != value64
)
220 doChangeValue
= true;
225 wxLongLong
ll(value64
);
231 if ( useText
.ToLong( &value32
, 0 ) )
233 if ( !isPrevLong
|| m_value
.GetLong() != value32
)
240 else if ( argFlags
& wxPG_REPORT_ERROR
)
246 bool wxIntProperty::IntToValue( wxVariant
& variant
, int value
, int WXUNUSED(argFlags
) ) const
248 if ( variant
.GetType() != wxPG_VARIANT_TYPE_LONG
|| variant
.GetLong() != value
)
250 variant
= (long)value
;
256 bool wxIntProperty::DoValidation( const wxPGProperty
* property
, wxLongLong_t
& value
, wxPGValidationInfo
* pValidationInfo
, int mode
)
259 wxLongLong_t min
= wxINT64_MIN
;
260 wxLongLong_t max
= wxINT64_MAX
;
265 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
);
266 if ( !variant
.IsNull() )
268 wxPGVariantToLongLong(variant
, &min
);
272 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
);
273 if ( !variant
.IsNull() )
275 wxPGVariantToLongLong(variant
, &max
);
283 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
284 pValidationInfo
->SetFailureMessage(
285 wxString::Format(_("Value must be %lld or higher"),min
)
287 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
290 value
= max
- (min
- value
);
299 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
300 pValidationInfo
->SetFailureMessage(
301 wxString::Format(_("Value must be %lld or higher"),min
)
303 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
306 value
= min
+ (value
- max
);
313 bool wxIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
316 if ( wxPGVariantToLongLong(value
, &ll
) )
317 return DoValidation(this, ll
, &validationInfo
, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
);
321 wxValidator
* wxIntProperty::GetClassValidator()
324 WX_PG_DOGETVALIDATOR_ENTRY()
326 // Atleast wxPython 2.6.2.1 required that the string argument is given
328 wxTextValidator
* validator
= new wxTextValidator(wxFILTER_NUMERIC
,&v
);
330 WX_PG_DOGETVALIDATOR_EXIT(validator
)
336 wxValidator
* wxIntProperty::DoGetValidator() const
338 return GetClassValidator();
341 // -----------------------------------------------------------------------
343 // -----------------------------------------------------------------------
346 #define wxPG_UINT_TEMPLATE_MAX 8
348 static const wxChar
* gs_uintTemplates32
[wxPG_UINT_TEMPLATE_MAX
] = {
349 wxT("%x"),wxT("0x%x"),wxT("$%x"),
350 wxT("%X"),wxT("0x%X"),wxT("$%X"),
354 static const wxChar
* gs_uintTemplates64
[wxPG_UINT_TEMPLATE_MAX
] = {
355 wxT("%") wxLongLongFmtSpec
wxT("x"),
356 wxT("0x%") wxLongLongFmtSpec
wxT("x"),
357 wxT("$%") wxLongLongFmtSpec
wxT("x"),
358 wxT("%") wxLongLongFmtSpec
wxT("X"),
359 wxT("0x%") wxLongLongFmtSpec
wxT("X"),
360 wxT("$%") wxLongLongFmtSpec
wxT("X"),
361 wxT("%") wxLongLongFmtSpec
wxT("u"),
362 wxT("%") wxLongLongFmtSpec
wxT("o")
365 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty
,wxPGProperty
,
366 long,unsigned long,TextCtrl
)
368 void wxUIntProperty::Init()
370 m_base
= 6; // This is magic number for dec base (must be same as in setattribute)
372 m_prefix
= wxPG_PREFIX_NONE
;
375 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
,
376 unsigned long value
) : wxPGProperty(label
,name
)
379 SetValue((long)value
);
382 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
,
383 const wxULongLong
& value
) : wxPGProperty(label
,name
)
386 SetValue(WXVARIANT(value
));
389 wxUIntProperty::~wxUIntProperty() { }
391 wxString
wxUIntProperty::GetValueAsString( int ) const
393 size_t index
= m_base
+ m_prefix
;
394 if ( index
>= wxPG_UINT_TEMPLATE_MAX
)
395 index
= wxPG_BASE_DEC
;
397 if ( m_value
.GetType() == wxPG_VARIANT_TYPE_LONG
)
399 return wxString::Format(gs_uintTemplates32
[index
], (unsigned long)m_value
.GetLong());
405 return wxString::Format(gs_uintTemplates64
[index
], ull
.GetValue());
408 bool wxUIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const
410 wxString variantType
= variant
.GetType();
411 bool isPrevLong
= variantType
== wxPG_VARIANT_TYPE_LONG
;
413 if ( text
.length() == 0 )
420 if ( text
[0] == wxS('$') )
423 wxULongLong_t value64
= 0;
424 wxString s
= text
.substr(start
, text
.length() - start
);
426 if ( s
.ToULongLong(&value64
, (unsigned int)m_realBase
) )
428 if ( value64
>= LONG_MAX
)
430 bool doChangeValue
= isPrevLong
;
432 if ( !isPrevLong
&& variantType
== wxULongLong_VariantType
)
434 wxULongLong oldValue
;
436 if ( oldValue
.GetValue() != value64
)
437 doChangeValue
= true;
442 wxULongLong
ull(value64
);
449 unsigned long value32
= wxLongLong(value64
).GetLo();
450 if ( !isPrevLong
|| m_value
.GetLong() != (long)value32
)
452 variant
= (long)value32
;
461 bool wxUIntProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
463 if ( m_value
!= (long)number
)
465 variant
= (long)number
;
472 #define wxUINT64_MAX ULLONG_MAX
473 #define wxUINT64_MIN wxULL(0)
475 #define wxUINT64_MAX wxULL(0xFFFFFFFFFFFFFFFF)
476 #define wxUINT64_MIN wxULL(0)
479 bool wxUIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
483 if ( wxPGVariantToULongLong(value
, &ll
) )
485 wxULongLong_t min
= wxUINT64_MIN
;
486 wxULongLong_t max
= wxUINT64_MAX
;
489 variant
= GetAttribute(wxPGGlobalVars
->m_strMin
);
490 if ( !variant
.IsNull() )
492 wxPGVariantToULongLong(variant
, &min
);
495 validationInfo
.SetFailureMessage(
496 wxString::Format(_("Value must be %llu or higher"),min
)
501 variant
= GetAttribute(wxPGGlobalVars
->m_strMax
);
502 if ( !variant
.IsNull() )
504 wxPGVariantToULongLong(variant
, &max
);
507 validationInfo
.SetFailureMessage(
508 wxString::Format(_("Value must be %llu or less"),max
)
517 bool wxUIntProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
519 if ( name
== wxPG_UINT_BASE
)
521 int val
= value
.GetLong();
523 m_realBase
= (wxByte
) val
;
524 if ( m_realBase
> 16 )
528 // Translate logical base to a template array index
530 if ( val
== wxPG_BASE_HEX
)
532 else if ( val
== wxPG_BASE_DEC
)
534 else if ( val
== wxPG_BASE_HEXL
)
538 else if ( name
== wxPG_UINT_PREFIX
)
540 m_prefix
= (wxByte
) value
.GetLong();
546 // -----------------------------------------------------------------------
548 // -----------------------------------------------------------------------
550 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty
,wxPGProperty
,
551 double,double,TextCtrl
)
553 wxFloatProperty::wxFloatProperty( const wxString
& label
,
554 const wxString
& name
,
556 : wxPGProperty(label
,name
)
562 wxFloatProperty::~wxFloatProperty() { }
564 // This helper method provides standard way for floating point-using
565 // properties to convert values to string.
566 void wxPropertyGrid::DoubleToString(wxString
& target
,
570 wxString
* precTemplate
)
572 if ( precision
>= 0 )
576 precTemplate
= &text1
;
578 if ( !precTemplate
->length() )
580 *precTemplate
= wxS("%.");
581 *precTemplate
<< wxString::Format( wxS("%i"), precision
);
582 *precTemplate
<< wxS('f');
585 target
.Printf( precTemplate
->c_str(), value
);
589 target
.Printf( wxS("%f"), value
);
592 if ( removeZeroes
&& precision
!= 0 && target
.length() )
594 // Remove excess zeroes (do not remove this code just yet,
595 // since sprintf can't do the same consistently across platforms).
596 wxString::const_iterator i
= target
.end() - 1;
597 size_t new_len
= target
.length() - 1;
599 for ( ; i
!= target
.begin(); i
-- )
601 if ( *i
!= wxS('0') )
606 wxChar cur_char
= *i
;
607 if ( cur_char
!= wxS('.') && cur_char
!= wxS(',') )
610 if ( new_len
!= target
.length() )
611 target
.resize(new_len
);
615 wxString
wxFloatProperty::GetValueAsString( int argFlags
) const
618 if ( !m_value
.IsNull() )
620 wxPropertyGrid::DoubleToString(text
,
623 !(argFlags
& wxPG_FULL_VALUE
),
629 bool wxFloatProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
634 if ( text
.length() == 0 )
640 bool res
= text
.ToDouble(&value
);
643 if ( m_value
!= value
)
649 else if ( argFlags
& wxPG_REPORT_ERROR
)
655 bool wxFloatProperty::DoValidation( const wxPGProperty
* property
, double& value
, wxPGValidationInfo
* pValidationInfo
, int mode
)
658 double min
= (double)wxINT64_MIN
;
659 double max
= (double)wxINT64_MAX
;
664 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
);
665 if ( !variant
.IsNull() )
667 wxPGVariantToDouble(variant
, &min
);
671 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
);
672 if ( !variant
.IsNull() )
674 wxPGVariantToDouble(variant
, &max
);
682 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
683 pValidationInfo
->SetFailureMessage(
684 wxString::Format(_("Value must be %f or higher"),min
)
686 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
689 value
= max
- (min
- value
);
696 wxPGVariantToDouble(variant
, &max
);
699 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
700 pValidationInfo
->SetFailureMessage(
701 wxString::Format(_("Value must be %f or less"),max
)
703 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
706 value
= min
+ (value
- max
);
713 bool wxFloatProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
716 if ( wxPGVariantToDouble(value
, &fpv
) )
717 return DoValidation(this, fpv
, &validationInfo
, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
);
721 bool wxFloatProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
723 if ( name
== wxPG_FLOAT_PRECISION
)
725 m_precision
= value
.GetLong();
731 wxValidator
* wxFloatProperty::DoGetValidator() const
733 return wxIntProperty::GetClassValidator();
736 // -----------------------------------------------------------------------
738 // -----------------------------------------------------------------------
740 // We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since
741 // there is a custom GetEditorClass.
743 IMPLEMENT_DYNAMIC_CLASS(wxBoolProperty
, wxPGProperty
)
745 const wxPGEditor
* wxBoolProperty::DoGetEditorClass() const
747 // Select correct editor control.
748 #if wxPG_INCLUDE_CHECKBOX
749 if ( !(m_flags
& wxPG_PROP_USE_CHECKBOX
) )
750 return wxPG_EDITOR(Choice
);
751 return wxPG_EDITOR(CheckBox
);
753 return wxPG_EDITOR(Choice
);
757 wxBoolProperty::wxBoolProperty( const wxString
& label
, const wxString
& name
, bool value
) :
758 wxPGProperty(label
,name
)
760 m_choices
.Assign(wxPGGlobalVars
->m_boolChoices
);
762 SetValue(wxPGVariant_Bool(value
));
764 m_flags
|= wxPG_PROP_USE_DCC
;
767 wxBoolProperty::~wxBoolProperty() { }
769 wxString
wxBoolProperty::GetValueAsString( int argFlags
) const
771 bool value
= m_value
.GetBool();
773 // As a fragment of composite string value,
774 // make it a little more readable.
775 if ( argFlags
& wxPG_COMPOSITE_FRAGMENT
)
783 if ( argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
)
784 return wxEmptyString
;
787 if ( wxPGGlobalVars
->m_autoGetTranslation
)
788 notFmt
= _("Not %s");
790 notFmt
= wxS("Not %s");
792 return wxString::Format(notFmt
.c_str(), m_label
.c_str());
796 if ( !(argFlags
& wxPG_FULL_VALUE
) )
798 return wxPGGlobalVars
->m_boolChoices
[value
?1:0].GetText();
803 if (value
) text
= wxS("true");
804 else text
= wxS("false");
809 bool wxBoolProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const
812 if ( text
.CmpNoCase(wxPGGlobalVars
->m_boolChoices
[1].GetText()) == 0 ||
813 text
.CmpNoCase(wxS("true")) == 0 ||
814 text
.CmpNoCase(m_label
) == 0 )
817 if ( text
.length() == 0 )
823 bool oldValue
= m_value
.GetBool();
825 if ( (oldValue
&& !value
) || (!oldValue
&& value
) )
827 variant
= wxPGVariant_Bool(value
);
833 bool wxBoolProperty::IntToValue( wxVariant
& variant
, int value
, int ) const
835 bool boolValue
= value
? true : false;
836 bool oldValue
= m_value
.GetBool();
838 if ( oldValue
!= boolValue
)
840 variant
= wxPGVariant_Bool(boolValue
);
846 bool wxBoolProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
848 #if wxPG_INCLUDE_CHECKBOX
849 if ( name
== wxPG_BOOL_USE_CHECKBOX
)
851 int ival
= wxPGVariantToInt(value
);
853 m_flags
|= wxPG_PROP_USE_CHECKBOX
;
855 m_flags
&= ~(wxPG_PROP_USE_CHECKBOX
);
859 if ( name
== wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING
)
861 int ival
= wxPGVariantToInt(value
);
863 m_flags
|= wxPG_PROP_USE_DCC
;
865 m_flags
&= ~(wxPG_PROP_USE_DCC
);
871 // -----------------------------------------------------------------------
872 // wxBaseEnumProperty
873 // -----------------------------------------------------------------------
875 int wxBaseEnumProperty::ms_nextIndex
= -2;
877 wxBaseEnumProperty::wxBaseEnumProperty( const wxString
& label
, const wxString
& name
)
878 : wxPGProperty(label
,name
)
880 m_value
= wxPGVariant_Zero
;
883 /** If has values array, then returns number at index with value -
884 otherwise just returns the value.
886 int wxBaseEnumProperty::GetIndexForValue( int value
) const
891 void wxBaseEnumProperty::OnSetValue()
893 wxString variantType
= m_value
.GetType();
895 if ( variantType
== wxPG_VARIANT_TYPE_LONG
)
896 ValueFromInt_( m_value
, m_value
.GetLong(), wxPG_FULL_VALUE
);
897 else if ( variantType
== wxPG_VARIANT_TYPE_STRING
)
898 ValueFromString_( m_value
, m_value
.GetString(), 0 );
902 if ( ms_nextIndex
!= -2 )
904 m_index
= ms_nextIndex
;
909 bool wxBaseEnumProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
911 // Make sure string value is in the list,
912 // unless property has string as preferred value type
913 // To reduce code size, use conversion here as well
914 if ( value
.GetType() == wxPG_VARIANT_TYPE_STRING
&&
915 !this->IsKindOf(CLASSINFO(wxEditEnumProperty
)) )
916 return ValueFromString_( value
, value
.GetString(), wxPG_PROPERTY_SPECIFIC
);
921 wxString
wxBaseEnumProperty::GetValueAsString( int ) const
923 if ( m_value
.GetType() == wxPG_VARIANT_TYPE_STRING
)
924 return m_value
.GetString();
929 const wxString
* pstr
= GetEntry( m_index
, &unusedVal
);
934 return wxEmptyString
;
937 bool wxBaseEnumProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
939 return ValueFromString_( variant
, text
, argFlags
);
942 bool wxBaseEnumProperty::IntToValue( wxVariant
& variant
, int intVal
, int argFlags
) const
944 return ValueFromInt_( variant
, intVal
, argFlags
);
947 bool wxBaseEnumProperty::ValueFromString_( wxVariant
& value
, const wxString
& text
, int argFlags
) const
950 const wxString
* entryLabel
;
955 entryLabel
= GetEntry(i
, &entryValue
);
958 if ( text
.CmpNoCase(*entryLabel
) == 0 )
961 useValue
= (long)entryValue
;
966 entryLabel
= GetEntry(i
, &entryValue
);
971 bool isEdit
= this->IsKindOf(CLASSINFO(wxEditEnumProperty
));
973 // If text not any of the choices, store as text instead
974 // (but only if we are wxEditEnumProperty)
975 if ( useIndex
== -1 &&
976 (value
.GetType() != wxPG_VARIANT_TYPE_STRING
|| (m_value
.GetString() != text
)) &&
982 int setAsNextIndex
= -2;
989 else if ( m_index
!= useIndex
)
991 if ( useIndex
!= -1 )
993 setAsNextIndex
= useIndex
;
994 value
= (long)useValue
;
999 value
= wxPGVariant_MinusOne
;
1003 if ( setAsNextIndex
!= -2 )
1005 // If wxPG_PROPERTY_SPECIFIC is set, then this is done for
1006 // validation purposes only, and index must not be changed
1007 if ( !(argFlags
& wxPG_PROPERTY_SPECIFIC
) )
1008 ms_nextIndex
= setAsNextIndex
;
1010 if ( isEdit
|| setAsNextIndex
!= -1 )
1018 bool wxBaseEnumProperty::ValueFromInt_( wxVariant
& variant
, int intVal
, int argFlags
) const
1020 // If wxPG_FULL_VALUE is *not* in argFlags, then intVal is index from combo box.
1024 if ( argFlags
& wxPG_FULL_VALUE
)
1026 ms_nextIndex
= GetIndexForValue( intVal
);
1030 if ( m_index
!= intVal
)
1032 ms_nextIndex
= intVal
;
1036 if ( ms_nextIndex
!= -2 )
1038 if ( !(argFlags
& wxPG_FULL_VALUE
) )
1039 GetEntry(intVal
, &intVal
);
1041 variant
= (long)intVal
;
1049 void wxBaseEnumProperty::SetIndex( int index
)
1055 int wxBaseEnumProperty::GetIndex() const
1057 if ( ms_nextIndex
!= -2 )
1058 return ms_nextIndex
;
1062 // -----------------------------------------------------------------------
1064 // -----------------------------------------------------------------------
1066 IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty
, wxPGProperty
)
1068 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty
,long,Choice
)
1070 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1071 const long* values
, int value
) : wxBaseEnumProperty(label
,name
)
1077 m_choices
.Add(labels
,values
);
1079 if ( GetItemCount() )
1080 SetValue( (long)value
);
1084 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1085 const long* values
, wxPGChoices
* choicesCache
, int value
)
1086 : wxBaseEnumProperty(label
,name
)
1090 wxASSERT( choicesCache
);
1092 if ( choicesCache
->IsOk() )
1094 m_choices
.Assign( *choicesCache
);
1095 m_value
= wxPGVariant_Zero
;
1099 m_choices
.Add(labels
,values
);
1101 if ( GetItemCount() )
1102 SetValue( (long)value
);
1106 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
,
1107 const wxArrayString
& labels
, const wxArrayInt
& values
, int value
) : wxBaseEnumProperty(label
,name
)
1111 if ( &labels
&& labels
.size() )
1113 m_choices
.Set(labels
, values
);
1115 if ( GetItemCount() )
1116 SetValue( (long)value
);
1120 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
,
1121 wxPGChoices
& choices
, int value
)
1122 : wxBaseEnumProperty(label
,name
)
1124 m_choices
.Assign( choices
);
1126 if ( GetItemCount() )
1127 SetValue( (long)value
);
1130 int wxEnumProperty::GetIndexForValue( int value
) const
1132 if ( !m_choices
.IsOk() )
1135 if ( m_choices
.HasValues() )
1137 int intVal
= m_choices
.Index(value
);
1145 wxEnumProperty::~wxEnumProperty ()
1149 const wxString
* wxEnumProperty::GetEntry( size_t index
, int* pvalue
) const
1151 if ( m_choices
.IsOk() && index
< m_choices
.GetCount() )
1153 int value
= (int)index
;
1154 if ( m_choices
.HasValue(index
) )
1155 value
= m_choices
.GetValue(index
);
1160 return &m_choices
.GetLabel(index
);
1162 return (const wxString
*) NULL
;
1165 // -----------------------------------------------------------------------
1166 // wxEditEnumProperty
1167 // -----------------------------------------------------------------------
1169 IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty
, wxPGProperty
)
1171 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty
,wxString
,ComboBox
)
1173 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1174 const long* values
, const wxString
& value
)
1175 : wxEnumProperty(label
,name
,labels
,values
,0)
1180 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1181 const long* values
, wxPGChoices
* choicesCache
, const wxString
& value
)
1182 : wxEnumProperty(label
,name
,labels
,values
,choicesCache
,0)
1187 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
,
1188 const wxArrayString
& labels
, const wxArrayInt
& values
, const wxString
& value
)
1189 : wxEnumProperty(label
,name
,labels
,values
,0)
1194 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
,
1195 wxPGChoices
& choices
, const wxString
& value
)
1196 : wxEnumProperty(label
,name
,choices
,0)
1201 wxEditEnumProperty::~wxEditEnumProperty()
1205 // -----------------------------------------------------------------------
1207 // -----------------------------------------------------------------------
1209 IMPLEMENT_DYNAMIC_CLASS(wxFlagsProperty
,wxPGProperty
)
1211 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty
,long,TextCtrl
)
1213 void wxFlagsProperty::Init()
1215 SetFlag(wxPG_PROP_AGGREGATE
); // This is must be done here to support flag props
1216 // with inital zero children.
1218 long value
= m_value
;
1221 // Generate children
1225 unsigned int prevChildCount
= m_children
.GetCount();
1228 if ( prevChildCount
)
1230 wxPropertyGridPageState
* state
= GetParentState();
1232 // State safety check (it may be NULL in immediate parent)
1237 wxPGProperty
* selected
= state
->GetSelection();
1240 if ( selected
->GetParent() == this )
1241 oldSel
= selected
->GetIndexInParent();
1242 else if ( selected
== this )
1246 state
->DoClearSelection();
1249 // Delete old children
1250 for ( i
=0; i
<prevChildCount
; i
++ )
1251 delete ( (wxPGProperty
*) m_children
[i
] );
1255 if ( m_choices
.IsOk() )
1257 const wxPGChoices
& choices
= m_choices
;
1259 for ( i
=0; i
<GetItemCount(); i
++ )
1262 if ( choices
.HasValue(i
) )
1263 child_val
= ( value
& choices
.GetValue(i
) )?true:false;
1265 child_val
= ( value
& (1<<i
) )?true:false;
1267 wxPGProperty
* boolProp
;
1268 wxString label
= GetLabel(i
);
1271 if ( wxPGGlobalVars
->m_autoGetTranslation
)
1273 boolProp
= new wxBoolProperty( ::wxGetTranslation(label
), label
, child_val
);
1278 boolProp
= new wxBoolProperty( label
, label
, child_val
);
1283 m_oldChoicesData
= m_choices
.GetDataPtr();
1286 m_oldValue
= m_value
;
1288 if ( prevChildCount
)
1289 SubPropsChanged(oldSel
);
1292 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1293 const wxChar
** labels
, const long* values
, long value
) : wxPGProperty(label
,name
)
1295 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1299 m_choices
.Set(labels
,values
);
1301 wxASSERT( GetItemCount() );
1307 m_value
= wxPGVariant_Zero
;
1311 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1312 const wxArrayString
& labels
, const wxArrayInt
& values
, int value
)
1313 : wxPGProperty(label
,name
)
1315 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1317 if ( &labels
&& labels
.size() )
1319 m_choices
.Set(labels
,values
);
1321 wxASSERT( GetItemCount() );
1323 SetValue( (long)value
);
1327 m_value
= wxPGVariant_Zero
;
1331 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1332 wxPGChoices
& choices
, long value
)
1333 : wxPGProperty(label
,name
)
1335 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1337 if ( choices
.IsOk() )
1339 m_choices
.Assign(choices
);
1341 wxASSERT( GetItemCount() );
1347 m_value
= wxPGVariant_Zero
;
1351 wxFlagsProperty::~wxFlagsProperty()
1355 void wxFlagsProperty::OnSetValue()
1357 if ( !m_choices
.IsOk() || !GetItemCount() )
1359 m_value
= wxPGVariant_Zero
;
1363 long val
= m_value
.GetLong();
1367 // normalize the value (i.e. remove extra flags)
1369 const wxPGChoices
& choices
= m_choices
;
1370 for ( i
= 0; i
< GetItemCount(); i
++ )
1372 if ( choices
.HasValue(i
) )
1373 fullFlags
|= choices
.GetValue(i
);
1375 fullFlags
|= (1<<i
);
1382 // Need to (re)init now?
1383 if ( GetChildCount() != GetItemCount() ||
1384 m_choices
.GetDataPtr() != m_oldChoicesData
)
1390 long newFlags
= m_value
;
1392 if ( newFlags
!= m_oldValue
)
1394 // Set child modified states
1396 const wxPGChoices
& choices
= m_choices
;
1397 for ( i
= 0; i
<GetItemCount(); i
++ )
1401 if ( choices
.HasValue(i
) )
1402 flag
= choices
.GetValue(i
);
1406 if ( (newFlags
& flag
) != (m_oldValue
& flag
) )
1407 Item(i
)->SetFlag( wxPG_PROP_MODIFIED
);
1410 m_oldValue
= newFlags
;
1414 wxString
wxFlagsProperty::GetValueAsString( int ) const
1418 if ( !m_choices
.IsOk() )
1421 long flags
= m_value
;
1423 const wxPGChoices
& choices
= m_choices
;
1425 for ( i
= 0; i
< GetItemCount(); i
++ )
1428 if ( choices
.HasValue(i
) )
1429 doAdd
= ( flags
& choices
.GetValue(i
) );
1431 doAdd
= ( flags
& (1<<i
) );
1435 text
+= choices
.GetLabel(i
);
1440 // remove last comma
1441 if ( text
.Len() > 1 )
1442 text
.Truncate ( text
.Len() - 2 );
1447 // Translate string into flag tokens
1448 bool wxFlagsProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
1450 if ( !m_choices
.IsOk() )
1454 long oldValue
= m_value
;
1456 // semicolons are no longer valid delimeters
1457 WX_PG_TOKENIZER1_BEGIN(text
,wxS(','))
1459 if ( token
.length() )
1461 // Determine which one it is
1462 long bit
= IdToBit( token
);
1475 WX_PG_TOKENIZER1_END()
1479 if ( newFlags
!= oldValue
)
1485 // Converts string id to a relevant bit.
1486 long wxFlagsProperty::IdToBit( const wxString
& id
) const
1489 for ( i
= 0; i
< GetItemCount(); i
++ )
1491 if ( id
== GetLabel(i
) )
1493 if ( m_choices
.HasValue(i
) )
1494 return m_choices
.GetValue(i
);
1501 void wxFlagsProperty::RefreshChildren()
1503 if ( !m_choices
.IsOk() || !GetChildCount() ) return;
1505 int flags
= m_value
.GetLong();
1507 const wxPGChoices
& choices
= m_choices
;
1509 for ( i
= 0; i
< GetItemCount(); i
++ )
1513 if ( choices
.HasValue(i
) )
1514 flag
= choices
.GetValue(i
);
1518 long subVal
= flags
& flag
;
1519 wxPGProperty
* p
= Item(i
);
1521 if ( subVal
!= (m_oldValue
& flag
) )
1522 p
->SetFlag( wxPG_PROP_MODIFIED
);
1524 p
->SetValue( subVal
?true:false );
1530 void wxFlagsProperty::ChildChanged( wxVariant
& thisValue
, int childIndex
, wxVariant
& childValue
) const
1532 long oldValue
= thisValue
.GetLong();
1533 long val
= childValue
.GetLong();
1534 unsigned long vi
= (1<<childIndex
);
1535 if ( m_choices
.HasValue(childIndex
) ) vi
= m_choices
.GetValue(childIndex
);
1537 thisValue
= (long)(oldValue
| vi
);
1539 thisValue
= (long)(oldValue
& ~(vi
));
1542 // -----------------------------------------------------------------------
1544 // -----------------------------------------------------------------------
1546 IMPLEMENT_DYNAMIC_CLASS(wxDirProperty
, wxLongStringProperty
)
1548 wxDirProperty::wxDirProperty( const wxString
& name
, const wxString
& label
, const wxString
& value
)
1549 : wxLongStringProperty(name
,label
,value
)
1551 m_flags
|= wxPG_NO_ESCAPE
;
1553 wxDirProperty::~wxDirProperty() { }
1555 wxValidator
* wxDirProperty::DoGetValidator() const
1557 return wxFileProperty::GetClassValidator();
1560 bool wxDirProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value
)
1562 wxSize
dlg_sz(300,400);
1564 wxDirDialog
dlg( propGrid
,
1565 m_dlgMessage
.length() ? m_dlgMessage
: wxString(_("Choose a directory:")),
1568 #if !wxPG_SMALL_SCREEN
1569 propGrid
->GetGoodEditorDialogPosition(this,dlg_sz
),
1576 if ( dlg
.ShowModal() == wxID_OK
)
1578 value
= dlg
.GetPath();
1584 bool wxDirProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1586 if ( name
== wxPG_DIR_DIALOG_MESSAGE
)
1588 m_dlgMessage
= value
.GetString();
1594 // -----------------------------------------------------------------------
1595 // wxPGFileDialogAdapter
1596 // -----------------------------------------------------------------------
1598 bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property
)
1600 wxFileProperty
* fileProp
= NULL
;
1604 if ( property
->IsKindOf(CLASSINFO(wxFileProperty
)) )
1606 fileProp
= ((wxFileProperty
*)property
);
1607 path
= fileProp
->m_filename
.GetPath();
1608 indFilter
= fileProp
->m_indFilter
;
1610 if ( !path
.length() && fileProp
->m_basePath
.length() )
1611 path
= fileProp
->m_basePath
;
1615 wxFileName
fn(property
->GetValue().GetString());
1616 path
= fn
.GetPath();
1619 wxFileDialog
dlg( propGrid
->GetPanel(),
1620 property
->GetAttribute(wxS("DialogTitle"), _("Choose a file")),
1621 property
->GetAttribute(wxS("InitialPath"), path
),
1623 property
->GetAttribute(wxPG_FILE_WILDCARD
, _("All files (*.*)|*.*")),
1625 wxDefaultPosition
);
1627 if ( indFilter
>= 0 )
1628 dlg
.SetFilterIndex( indFilter
);
1630 if ( dlg
.ShowModal() == wxID_OK
)
1633 fileProp
->m_indFilter
= dlg
.GetFilterIndex();
1634 SetValue( dlg
.GetPath() );
1640 // -----------------------------------------------------------------------
1642 // -----------------------------------------------------------------------
1644 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty
,wxPGProperty
,
1645 wxString
,const wxString
&,TextCtrlAndButton
)
1647 wxFileProperty::wxFileProperty( const wxString
& label
, const wxString
& name
,
1648 const wxString
& value
) : wxPGProperty(label
,name
)
1650 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1652 SetAttribute( wxPG_FILE_WILDCARD
, _("All files (*.*)|*.*") );
1657 wxFileProperty::~wxFileProperty() {}
1659 #if wxUSE_VALIDATORS
1661 wxValidator
* wxFileProperty::GetClassValidator()
1663 WX_PG_DOGETVALIDATOR_ENTRY()
1665 // Atleast wxPython 2.6.2.1 required that the string argument is given
1667 wxTextValidator
* validator
= new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST
,&v
);
1669 wxArrayString exChars
;
1670 exChars
.Add(wxS("?"));
1671 exChars
.Add(wxS("*"));
1672 exChars
.Add(wxS("|"));
1673 exChars
.Add(wxS("<"));
1674 exChars
.Add(wxS(">"));
1675 exChars
.Add(wxS("\""));
1677 validator
->SetExcludes(exChars
);
1679 WX_PG_DOGETVALIDATOR_EXIT(validator
)
1682 wxValidator
* wxFileProperty::DoGetValidator() const
1684 return GetClassValidator();
1689 void wxFileProperty::OnSetValue()
1691 const wxString
& fnstr
= m_value
.GetString();
1695 if ( !m_filename
.HasName() )
1697 m_value
= wxPGVariant_EmptyString
;
1701 // Find index for extension.
1702 if ( m_indFilter
< 0 && fnstr
.length() )
1704 wxString ext
= m_filename
.GetExt();
1707 size_t len
= m_wildcard
.length();
1709 pos
= m_wildcard
.find(wxS("|"), pos
);
1710 while ( pos
!= wxString::npos
&& pos
< (len
-3) )
1712 size_t ext_begin
= pos
+ 3;
1714 pos
= m_wildcard
.find(wxS("|"), ext_begin
);
1715 if ( pos
== wxString::npos
)
1717 wxString found_ext
= m_wildcard
.substr(ext_begin
, pos
-ext_begin
);
1719 if ( found_ext
.length() > 0 )
1721 if ( found_ext
[0] == wxS('*') )
1723 m_indFilter
= curind
;
1726 if ( ext
.CmpNoCase(found_ext
) == 0 )
1728 m_indFilter
= curind
;
1734 pos
= m_wildcard
.find(wxS("|"), pos
+1);
1741 wxString
wxFileProperty::GetValueAsString( int argFlags
) const
1743 // Always return empty string when name component is empty
1744 wxString fullName
= m_filename
.GetFullName();
1745 if ( !fullName
.length() )
1748 if ( argFlags
& wxPG_FULL_VALUE
)
1750 return m_filename
.GetFullPath();
1752 else if ( m_flags
& wxPG_PROP_SHOW_FULL_FILENAME
)
1754 if ( m_basePath
.Length() )
1756 wxFileName
fn2(m_filename
);
1757 fn2
.MakeRelativeTo(m_basePath
);
1758 return fn2
.GetFullPath();
1760 return m_filename
.GetFullPath();
1763 return m_filename
.GetFullName();
1766 wxPGEditorDialogAdapter
* wxFileProperty::GetEditorDialog() const
1768 return new wxPGFileDialogAdapter();
1771 bool wxFileProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
1773 if ( (m_flags
& wxPG_PROP_SHOW_FULL_FILENAME
) || (argFlags
& wxPG_FULL_VALUE
) )
1775 if ( m_filename
!= text
)
1783 if ( m_filename
.GetFullName() != text
)
1785 wxFileName fn
= m_filename
;
1786 fn
.SetFullName(text
);
1787 variant
= fn
.GetFullPath();
1795 bool wxFileProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1797 // Return false on some occasions to make sure those attribs will get
1798 // stored in m_attributes.
1799 if ( name
== wxPG_FILE_SHOW_FULL_PATH
)
1801 if ( wxPGVariantToInt(value
) )
1802 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1804 m_flags
&= ~(wxPG_PROP_SHOW_FULL_FILENAME
);
1807 else if ( name
== wxPG_FILE_WILDCARD
)
1809 m_wildcard
= value
.GetString();
1811 else if ( name
== wxPG_FILE_SHOW_RELATIVE_PATH
)
1813 m_basePath
= value
.GetString();
1815 // Make sure wxPG_FILE_SHOW_FULL_PATH is also set
1816 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1818 else if ( name
== wxPG_FILE_INITIAL_PATH
)
1820 m_initialPath
= value
.GetString();
1823 else if ( name
== wxPG_FILE_DIALOG_TITLE
)
1825 m_dlgTitle
= value
.GetString();
1831 // -----------------------------------------------------------------------
1832 // wxPGLongStringDialogAdapter
1833 // -----------------------------------------------------------------------
1835 bool wxPGLongStringDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property
)
1837 wxString val1
= property
->GetValueAsString(0);
1838 wxString val_orig
= val1
;
1841 if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) )
1842 wxPropertyGrid::ExpandEscapeSequences(value
, val1
);
1844 value
= wxString(val1
);
1846 // Run editor dialog.
1847 if ( wxLongStringProperty::DisplayEditorDialog(property
, propGrid
, value
) )
1849 if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) )
1850 wxPropertyGrid::CreateEscapeSequences(val1
,value
);
1854 if ( val1
!= val_orig
)
1863 // -----------------------------------------------------------------------
1864 // wxLongStringProperty
1865 // -----------------------------------------------------------------------
1867 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty
,wxPGProperty
,
1868 wxString
,const wxString
&,TextCtrlAndButton
)
1870 wxLongStringProperty::wxLongStringProperty( const wxString
& label
, const wxString
& name
,
1871 const wxString
& value
) : wxPGProperty(label
,name
)
1876 wxLongStringProperty::~wxLongStringProperty() {}
1878 wxString
wxLongStringProperty::GetValueAsString( int ) const
1883 bool wxLongStringProperty::OnEvent( wxPropertyGrid
* propGrid
, wxWindow
* WXUNUSED(primary
),
1886 if ( propGrid
->IsMainButtonEvent(event
) )
1889 PrepareValueForDialogEditing(propGrid
);
1891 wxString val1
= GetValueAsString(0);
1892 wxString val_orig
= val1
;
1895 if ( !(m_flags
& wxPG_PROP_NO_ESCAPE
) )
1896 wxPropertyGrid::ExpandEscapeSequences(value
,val1
);
1898 value
= wxString(val1
);
1900 // Run editor dialog.
1901 if ( OnButtonClick(propGrid
,value
) )
1903 if ( !(m_flags
& wxPG_PROP_NO_ESCAPE
) )
1904 wxPropertyGrid::CreateEscapeSequences(val1
,value
);
1908 if ( val1
!= val_orig
)
1910 SetValueInEvent( val1
);
1918 bool wxLongStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value
)
1920 return DisplayEditorDialog(this, propGrid
, value
);
1923 bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty
* prop
, wxPropertyGrid
* propGrid
, wxString
& value
)
1926 // launch editor dialog
1927 wxDialog
* dlg
= new wxDialog(propGrid
,-1,prop
->GetLabel(),wxDefaultPosition
,wxDefaultSize
,
1928 wxDEFAULT_DIALOG_STYLE
|wxRESIZE_BORDER
|wxCLIP_CHILDREN
);
1930 dlg
->SetFont(propGrid
->GetFont()); // To allow entering chars of the same set as the propGrid
1932 // Multi-line text editor dialog.
1933 #if !wxPG_SMALL_SCREEN
1934 const int spacing
= 8;
1936 const int spacing
= 4;
1938 wxBoxSizer
* topsizer
= new wxBoxSizer( wxVERTICAL
);
1939 wxBoxSizer
* rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
1940 wxTextCtrl
* ed
= new wxTextCtrl(dlg
,11,value
,
1941 wxDefaultPosition
,wxDefaultSize
,wxTE_MULTILINE
);
1943 rowsizer
->Add( ed
, 1, wxEXPAND
|wxALL
, spacing
);
1944 topsizer
->Add( rowsizer
, 1, wxEXPAND
, 0 );
1945 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
1946 const int but_sz_flags
=
1947 wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxBOTTOM
|wxLEFT
|wxRIGHT
;
1948 rowsizer
->Add( new wxButton(dlg
,wxID_OK
,_("Ok")),
1949 0, but_sz_flags
, spacing
);
1950 rowsizer
->Add( new wxButton(dlg
,wxID_CANCEL
,_("Cancel")),
1951 0, but_sz_flags
, spacing
);
1952 topsizer
->Add( rowsizer
, 0, wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
, 0 );
1954 dlg
->SetSizer( topsizer
);
1955 topsizer
->SetSizeHints( dlg
);
1957 #if !wxPG_SMALL_SCREEN
1958 dlg
->SetSize(400,300);
1960 dlg
->Move( propGrid
->GetGoodEditorDialogPosition(prop
,dlg
->GetSize()) );
1963 int res
= dlg
->ShowModal();
1965 if ( res
== wxID_OK
)
1967 value
= ed
->GetValue();
1975 bool wxLongStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
1977 if ( m_value
!= text
)
1985 // -----------------------------------------------------------------------
1986 // wxArrayEditorDialog
1987 // -----------------------------------------------------------------------
1989 BEGIN_EVENT_TABLE(wxArrayEditorDialog
, wxDialog
)
1990 EVT_IDLE(wxArrayEditorDialog::OnIdle
)
1991 EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick
)
1992 EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick
)
1993 EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick
)
1994 EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick
)
1995 EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick
)
1996 EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick
)
1997 EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick
)
1998 //EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick)
2001 IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog
, wxDialog
)
2003 #include <wx/statline.h>
2005 // -----------------------------------------------------------------------
2007 void wxArrayEditorDialog::OnIdle(wxIdleEvent
& event
)
2010 // Do control focus detection here.
2013 wxWindow
* focused
= FindFocus();
2015 // This strange focus thing is a workaround for wxGTK wxListBox focus
2017 if ( m_curFocus
== 0 && focused
!= m_edValue
&&
2018 focused
!= m_butAdd
&& focused
!= m_butUpdate
&&
2019 m_lbStrings
->GetSelection() >= 0 )
2021 // ListBox was just focused.
2022 m_butAdd
->Enable(false);
2023 m_butUpdate
->Enable(false);
2024 m_butRemove
->Enable(true);
2025 m_butUp
->Enable(true);
2026 m_butDown
->Enable(true);
2029 else if ( (m_curFocus
== 1 && focused
== m_edValue
) /*|| m_curFocus == 2*/ )
2031 // TextCtrl was just focused.
2032 m_butAdd
->Enable(true);
2033 bool upd_enable
= false;
2034 if ( m_lbStrings
->GetCount() && m_lbStrings
->GetSelection() >= 0 )
2036 m_butUpdate
->Enable(upd_enable
);
2037 m_butRemove
->Enable(false);
2038 m_butUp
->Enable(false);
2039 m_butDown
->Enable(false);
2046 // -----------------------------------------------------------------------
2048 wxArrayEditorDialog::wxArrayEditorDialog()
2054 // -----------------------------------------------------------------------
2056 void wxArrayEditorDialog::Init()
2058 m_custBtText
= (const wxChar
*) NULL
;
2061 // -----------------------------------------------------------------------
2063 wxArrayEditorDialog::wxArrayEditorDialog( wxWindow
*parent
,
2064 const wxString
& message
,
2065 const wxString
& caption
,
2072 Create(parent
,message
,caption
,style
,pos
,sz
);
2075 // -----------------------------------------------------------------------
2077 bool wxArrayEditorDialog::Create( wxWindow
*parent
,
2078 const wxString
& message
,
2079 const wxString
& caption
,
2084 // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION
2085 // FIXME: This should be only a temporary fix.
2087 int useStyle
= wxCAPTION
;
2089 int useStyle
= style
;
2092 bool res
= wxDialog::Create(parent
, wxID_ANY
, caption
, pos
, sz
, useStyle
);
2094 SetFont(parent
->GetFont()); // To allow entering chars of the same set as the propGrid
2096 #if !wxPG_SMALL_SCREEN
2097 const int spacing
= 4;
2099 const int spacing
= 3;
2106 const int but_sz_flags
=
2107 wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxALL
; //wxBOTTOM|wxLEFT|wxRIGHT;
2109 wxBoxSizer
* topsizer
= new wxBoxSizer( wxVERTICAL
);
2112 if ( message
.length() )
2113 topsizer
->Add( new wxStaticText(this,-1,message
),
2114 0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing
);
2117 wxBoxSizer
* rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2118 m_edValue
= new wxTextCtrl(this,21,wxEmptyString
,
2119 wxDefaultPosition
,wxDefaultSize
,wxTE_PROCESS_ENTER
);
2120 wxValidator
* validator
= GetTextCtrlValidator();
2123 m_edValue
->SetValidator( *validator
);
2126 rowsizer
->Add( m_edValue
,
2127 1, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing
);
2130 m_butAdd
= new wxButton(this,22,_("Add"));
2131 rowsizer
->Add( m_butAdd
,
2132 0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxTOP
|wxBOTTOM
|wxRIGHT
, spacing
);
2133 topsizer
->Add( rowsizer
, 0, wxEXPAND
, spacing
);
2136 topsizer
->Add( new wxStaticLine(this,-1),
2137 0, wxEXPAND
|wxBOTTOM
|wxLEFT
|wxRIGHT
, spacing
);
2139 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2142 m_lbStrings
= new wxListBox(this, 24, wxDefaultPosition
, wxDefaultSize
);
2144 for ( i
=0; i
<ArrayGetCount(); i
++ )
2145 m_lbStrings
->Append( ArrayGet(i
) );
2146 rowsizer
->Add( m_lbStrings
, 1, wxEXPAND
|wxRIGHT
, spacing
);
2148 // Manipulator buttons
2149 wxBoxSizer
* colsizer
= new wxBoxSizer( wxVERTICAL
);
2150 m_butCustom
= (wxButton
*) NULL
;
2153 m_butCustom
= new wxButton(this,28,::wxGetTranslation(m_custBtText
));
2154 colsizer
->Add( m_butCustom
,
2155 0, wxALIGN_CENTER
|wxTOP
/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/,
2158 m_butUpdate
= new wxButton(this,27,_("Update"));
2159 colsizer
->Add( m_butUpdate
,
2160 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2161 m_butRemove
= new wxButton(this,23,_("Remove"));
2162 colsizer
->Add( m_butRemove
,
2163 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2164 m_butUp
= new wxButton(this,25,_("Up"));
2165 colsizer
->Add( m_butUp
,
2166 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2167 m_butDown
= new wxButton(this,26,_("Down"));
2168 colsizer
->Add( m_butDown
,
2169 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2170 rowsizer
->Add( colsizer
, 0, 0, spacing
);
2172 topsizer
->Add( rowsizer
, 1, wxLEFT
|wxRIGHT
|wxEXPAND
, spacing
);
2175 topsizer
->Add( new wxStaticLine(this,-1),
2176 0, wxEXPAND
|wxTOP
|wxLEFT
|wxRIGHT
, spacing
);
2179 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2181 const int but_sz_flags =
2182 wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT;
2184 rowsizer
->Add( new wxButton(this,wxID_OK
,_("Ok")),
2185 0, but_sz_flags
, spacing
);
2186 rowsizer
->Add( new wxButton(this,wxID_CANCEL
,_("Cancel")),
2187 0, but_sz_flags
, spacing
);
2188 topsizer
->Add( rowsizer
, 0, wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
, 0 );
2190 m_edValue
->SetFocus();
2192 SetSizer( topsizer
);
2193 topsizer
->SetSizeHints( this );
2195 #if !wxPG_SMALL_SCREEN
2196 if ( sz
.x
== wxDefaultSize
.x
&&
2197 sz
.y
== wxDefaultSize
.y
)
2198 SetSize( wxSize(275,360) );
2206 // -----------------------------------------------------------------------
2208 void wxArrayEditorDialog::OnAddClick(wxCommandEvent
& )
2210 wxString text
= m_edValue
->GetValue();
2211 if ( text
.length() )
2213 if ( ArrayInsert( text
, -1 ) )
2215 m_lbStrings
->Append( text
);
2222 // -----------------------------------------------------------------------
2224 void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent
& )
2226 int index
= m_lbStrings
->GetSelection();
2229 ArrayRemoveAt( index
);
2230 m_lbStrings
->Delete ( index
);
2235 // -----------------------------------------------------------------------
2237 void wxArrayEditorDialog::OnUpClick(wxCommandEvent
& )
2239 int index
= m_lbStrings
->GetSelection();
2242 ArraySwap(index
-1,index
);
2243 /*wxString old_str = m_array[index-1];
2244 wxString new_str = m_array[index];
2245 m_array[index-1] = new_str;
2246 m_array[index] = old_str;*/
2247 m_lbStrings
->SetString ( index
-1, ArrayGet(index
-1) );
2248 m_lbStrings
->SetString ( index
, ArrayGet(index
) );
2249 m_lbStrings
->SetSelection ( index
-1 );
2254 // -----------------------------------------------------------------------
2256 void wxArrayEditorDialog::OnDownClick(wxCommandEvent
& )
2258 int index
= m_lbStrings
->GetSelection();
2259 int lastStringIndex
= ((int) m_lbStrings
->GetCount()) - 1;
2260 if ( index
>= 0 && index
< lastStringIndex
)
2262 ArraySwap(index
,index
+1);
2263 /*wxString old_str = m_array[index+1];
2264 wxString new_str = m_array[index];
2265 m_array[index+1] = new_str;
2266 m_array[index] = old_str;*/
2267 m_lbStrings
->SetString ( index
+1, ArrayGet(index
+1) );
2268 m_lbStrings
->SetString ( index
, ArrayGet(index
) );
2269 m_lbStrings
->SetSelection ( index
+1 );
2274 // -----------------------------------------------------------------------
2276 void wxArrayEditorDialog::OnUpdateClick(wxCommandEvent
& )
2278 int index
= m_lbStrings
->GetSelection();
2281 wxString str
= m_edValue
->GetValue();
2282 if ( ArraySet(index
,str
) )
2284 m_lbStrings
->SetString ( index
, str
);
2285 //m_array[index] = str;
2291 // -----------------------------------------------------------------------
2293 void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent
& )
2295 int index
= m_lbStrings
->GetSelection();
2298 m_edValue
->SetValue( m_lbStrings
->GetString(index
) );
2302 // -----------------------------------------------------------------------
2303 // wxPGArrayStringEditorDialog
2304 // -----------------------------------------------------------------------
2306 IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog
, wxArrayEditorDialog
)
2308 BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog
, wxArrayEditorDialog
)
2309 EVT_BUTTON(28, wxPGArrayStringEditorDialog::OnCustomEditClick
)
2312 // -----------------------------------------------------------------------
2314 wxString
wxPGArrayStringEditorDialog::ArrayGet( size_t index
)
2316 return m_array
[index
];
2319 size_t wxPGArrayStringEditorDialog::ArrayGetCount()
2321 return m_array
.size();
2324 bool wxPGArrayStringEditorDialog::ArrayInsert( const wxString
& str
, int index
)
2329 m_array
.Insert(str
,index
);
2333 bool wxPGArrayStringEditorDialog::ArraySet( size_t index
, const wxString
& str
)
2335 m_array
[index
] = str
;
2339 void wxPGArrayStringEditorDialog::ArrayRemoveAt( int index
)
2341 m_array
.RemoveAt(index
);
2344 void wxPGArrayStringEditorDialog::ArraySwap( size_t first
, size_t second
)
2346 wxString old_str
= m_array
[first
];
2347 wxString new_str
= m_array
[second
];
2348 m_array
[first
] = new_str
;
2349 m_array
[second
] = old_str
;
2352 wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog()
2353 : wxArrayEditorDialog()
2358 void wxPGArrayStringEditorDialog::Init()
2360 m_pCallingClass
= (wxArrayStringProperty
*) NULL
;
2363 void wxPGArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent
& )
2365 wxASSERT( m_pCallingClass
);
2366 wxString str
= m_edValue
->GetValue();
2367 if ( m_pCallingClass
->OnCustomStringEdit(m_parent
,str
) )
2369 //m_edValue->SetValue ( str );
2370 m_lbStrings
->Append ( str
);
2371 m_array
.Add ( str
);
2376 // -----------------------------------------------------------------------
2377 // wxArrayStringProperty
2378 // -----------------------------------------------------------------------
2380 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty
, // Property name
2381 wxPGProperty
, // Property we inherit from
2382 wxArrayString
, // Value type name
2383 const wxArrayString
&, // Value type, as given in constructor
2384 TextCtrlAndButton
) // Initial editor
2386 wxArrayStringProperty::wxArrayStringProperty( const wxString
& label
,
2387 const wxString
& name
,
2388 const wxArrayString
& array
)
2389 : wxPGProperty(label
,name
)
2394 wxArrayStringProperty::~wxArrayStringProperty() { }
2396 void wxArrayStringProperty::OnSetValue()
2398 GenerateValueAsString();
2401 wxString
wxArrayStringProperty::GetValueAsString( int WXUNUSED(argFlags
) ) const
2406 // Converts wxArrayString to a string separated by delimeters and spaces.
2407 // preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash
2409 void wxPropertyGrid::ArrayStringToString( wxString
& dst
, const wxArrayString
& src
,
2410 wxChar preDelim
, wxChar postDelim
,
2416 unsigned int itemCount
= src
.size();
2424 else if ( (flags
& 1) )
2426 preas
[0] = preDelim
;
2433 dst
.append( preas
);
2435 wxASSERT( postDelim
);
2436 wxString
postDelimStr(postDelim
);
2437 //wxString preDelimStr(preDelim);
2439 for ( i
= 0; i
< itemCount
; i
++ )
2441 wxString
str( src
.Item(i
) );
2443 // Do some character conversion.
2444 // Convertes \ to \\ and <preDelim> to \<preDelim>
2445 // Useful when preDelim and postDelim are "\"".
2448 str
.Replace( wxS("\\"), wxS("\\\\"), true );
2450 str
.Replace( preas
, pdr
, true );
2455 if ( i
< (itemCount
-1) )
2457 dst
.append( postDelimStr
);
2458 dst
.append( wxS(" ") );
2459 dst
.append( preas
);
2461 else if ( preDelim
)
2462 dst
.append( postDelimStr
);
2466 #define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \
2467 wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxS('"'),wxS('"'),1);
2469 void wxArrayStringProperty::GenerateValueAsString()
2471 wxArrayString arr
= m_value
.GetArrayString();
2472 ARRSTRPROP_ARRAY_TO_STRING(m_display
, arr
)
2475 // Default implementation doesn't do anything.
2476 bool wxArrayStringProperty::OnCustomStringEdit( wxWindow
*, wxString
& )
2481 wxArrayEditorDialog
* wxArrayStringProperty::CreateEditorDialog()
2483 return new wxPGArrayStringEditorDialog();
2486 bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
,
2487 wxWindow
* WXUNUSED(primaryCtrl
),
2491 PrepareValueForDialogEditing(propGrid
);
2493 if ( !propGrid
->EditorValidate() )
2496 // Create editor dialog.
2497 wxArrayEditorDialog
* dlg
= CreateEditorDialog();
2498 #if wxUSE_VALIDATORS
2499 wxValidator
* validator
= GetValidator();
2500 wxPGInDialogValidator dialogValidator
;
2503 wxPGArrayStringEditorDialog
* strEdDlg
= wxDynamicCast(dlg
, wxPGArrayStringEditorDialog
);
2506 strEdDlg
->SetCustomButton(cbt
, this);
2508 dlg
->SetDialogValue( wxVariant(m_value
) );
2509 dlg
->Create(propGrid
, wxEmptyString
, m_label
);
2511 #if !wxPG_SMALL_SCREEN
2512 dlg
->Move( propGrid
->GetGoodEditorDialogPosition(this,dlg
->GetSize()) );
2521 int res
= dlg
->ShowModal();
2523 if ( res
== wxID_OK
&& dlg
->IsModified() )
2525 wxVariant value
= dlg
->GetDialogValue();
2526 if ( !value
.IsNull() )
2528 wxArrayString actualValue
= value
.GetArrayString();
2530 ARRSTRPROP_ARRAY_TO_STRING(tempStr
, actualValue
)
2531 #if wxUSE_VALIDATORS
2532 if ( dialogValidator
.DoValidate( propGrid
, validator
, tempStr
) )
2535 SetValueInEvent( actualValue
);
2552 bool wxArrayStringProperty::OnEvent( wxPropertyGrid
* propGrid
,
2556 if ( propGrid
->IsMainButtonEvent(event
) )
2557 return OnButtonClick(propGrid
,primary
,(const wxChar
*) NULL
);
2561 bool wxArrayStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
2565 WX_PG_TOKENIZER2_BEGIN(text
,wxS('"'))
2567 // Need to replace backslashes with empty characters
2568 // (opposite what is done in GenerateValueString).
2569 token
.Replace ( wxS("\\"), wxEmptyString
, true );
2573 WX_PG_TOKENIZER2_END()
2580 // -----------------------------------------------------------------------
2581 // wxPGInDialogValidator
2582 // -----------------------------------------------------------------------
2584 #if wxUSE_VALIDATORS
2585 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* propGrid
,
2586 wxValidator
* validator
,
2587 const wxString
& value
)
2592 wxTextCtrl
* tc
= m_textCtrl
;
2597 tc
= new wxTextCtrl( propGrid
, wxPG_SUBID_TEMP1
, wxEmptyString
,
2598 wxPoint(30000,30000));
2605 tc
->SetValue(value
);
2607 validator
->SetWindow(tc
);
2608 bool res
= validator
->Validate(propGrid
);
2613 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* WXUNUSED(propGrid
),
2614 wxValidator
* WXUNUSED(validator
),
2615 const wxString
& WXUNUSED(value
) )
2621 // -----------------------------------------------------------------------
2623 #endif // wxUSE_PROPGRID