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"
21 #include "wx/object.h"
23 #include "wx/string.h"
26 #include "wx/window.h"
29 #include "wx/dcclient.h"
30 #include "wx/dcmemory.h"
31 #include "wx/button.h"
34 #include "wx/cursor.h"
35 #include "wx/dialog.h"
36 #include "wx/settings.h"
37 #include "wx/msgdlg.h"
38 #include "wx/choice.h"
39 #include "wx/stattext.h"
40 #include "wx/scrolwin.h"
41 #include "wx/dirdlg.h"
42 #include "wx/combobox.h"
43 #include "wx/layout.h"
45 #include "wx/textdlg.h"
46 #include "wx/filedlg.h"
47 #include "wx/statusbr.h"
51 #include <wx/filename.h>
53 #include <wx/propgrid/propgrid.h>
55 #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc.
58 // -----------------------------------------------------------------------
60 // -----------------------------------------------------------------------
62 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty
,wxPGProperty
,
63 wxString
,const wxString
&,TextCtrl
)
65 wxStringProperty::wxStringProperty( const wxString
& label
,
67 const wxString
& value
)
68 : wxPGProperty(label
,name
)
73 void wxStringProperty::OnSetValue()
75 if ( !m_value
.IsNull() && m_value
.GetString() == wxS("<composed>") )
76 SetFlag(wxPG_PROP_COMPOSED_VALUE
);
78 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
81 GenerateComposedValue(s
, 0);
86 wxStringProperty::~wxStringProperty() { }
88 wxString
wxStringProperty::GetValueAsString( int argFlags
) const
90 wxString s
= m_value
.GetString();
92 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
94 // Value stored in m_value is non-editable, non-full value
95 if ( (argFlags
& wxPG_FULL_VALUE
) || (argFlags
& wxPG_EDITABLE_VALUE
) )
96 GenerateComposedValue(s
, argFlags
);
101 // If string is password and value is for visual purposes,
102 // then return asterisks instead the actual string.
103 if ( (m_flags
& wxPG_PROP_PASSWORD
) && !(argFlags
& (wxPG_FULL_VALUE
|wxPG_EDITABLE_VALUE
)) )
104 return wxString(wxChar('*'), s
.Length());
109 bool wxStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
111 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
112 return wxPGProperty::StringToValue(variant
, text
, argFlags
);
114 if ( m_value
.GetString() != text
)
123 bool wxStringProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
125 if ( name
== wxPG_STRING_PASSWORD
)
127 m_flags
&= ~(wxPG_PROP_PASSWORD
);
128 if ( wxPGVariantToInt(value
) ) m_flags
|= wxPG_PROP_PASSWORD
;
135 // -----------------------------------------------------------------------
137 // -----------------------------------------------------------------------
139 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty
,wxPGProperty
,
142 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
,
143 long value
) : wxPGProperty(label
,name
)
148 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
,
149 const wxLongLong
& value
) : wxPGProperty(label
,name
)
151 SetValue(wxLongLongToVariant(value
));
154 wxIntProperty::~wxIntProperty() { }
156 wxString
wxIntProperty::GetValueAsString( int ) const
158 if ( wxPGIsVariantType(m_value
, long) )
159 return wxString::Format(wxS("%li"),m_value
.GetLong());
161 wxLongLong
* ll
= &wxLongLongFromVariant(m_value
);
163 return ll
->ToString();
165 return wxEmptyString
;
168 bool wxIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
173 if ( text
.length() == 0 )
179 // We know it is a number, but let's still check
181 if ( text
.IsNumber() )
183 // Remove leading zeroes, so that the number is not interpreted as octal
184 wxString::const_iterator i
= text
.begin();
185 wxString::const_iterator iMax
= text
.end() - 1; // Let's allow one, last zero though
187 int firstNonZeroPos
= 0;
189 for ( ; i
!= iMax
; i
++ )
192 if ( c
!= wxS('0') && c
!= wxS(' ') )
197 wxString useText
= text
.substr(firstNonZeroPos
, text
.length() - firstNonZeroPos
);
199 bool isPrevLong
= wxPGIsVariantType(variant
, long);
201 wxLongLong_t value64
= 0;
203 if ( useText
.ToLongLong(&value64
, 10) &&
204 ( value64
>= INT_MAX
|| value64
<= INT_MIN
)
207 wxLongLong
* _m_value64
= &wxLongLongFromVariant(m_value
);
208 if ( isPrevLong
|| !_m_value64
|| _m_value64
->GetValue() != value64
)
210 variant
= wxLongLongToVariant(value64
);
215 if ( useText
.ToLong( &value32
, 0 ) )
217 if ( !isPrevLong
|| m_value
.GetLong() != value32
)
224 else if ( argFlags
& wxPG_REPORT_ERROR
)
230 bool wxIntProperty::IntToValue( wxVariant
& variant
, int value
, int WXUNUSED(argFlags
) ) const
232 if ( !wxPGIsVariantType(variant
, long) || variant
.GetLong() != value
)
234 variant
= (long)value
;
240 bool wxIntProperty::DoValidation( const wxPGProperty
* property
, wxLongLong_t
& value
, wxPGValidationInfo
* pValidationInfo
, int mode
)
243 wxLongLong_t min
= wxINT64_MIN
;
244 wxLongLong_t max
= wxINT64_MAX
;
249 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
);
250 if ( !variant
.IsNull() )
252 wxPGVariantToLongLong(variant
, &min
);
256 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
);
257 if ( !variant
.IsNull() )
259 wxPGVariantToLongLong(variant
, &max
);
267 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
268 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %lld or higher"),min
);
269 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
272 value
= max
- (min
- value
);
281 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
282 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %lld or higher"),min
);
283 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
286 value
= min
+ (value
- max
);
293 bool wxIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
296 if ( wxPGVariantToLongLong(value
, &ll
) )
297 return DoValidation(this, ll
, &validationInfo
, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
);
301 wxValidator
* wxIntProperty::GetClassValidator()
304 WX_PG_DOGETVALIDATOR_ENTRY()
306 // Atleast wxPython 2.6.2.1 required that the string argument is given
308 wxTextValidator
* validator
= new wxTextValidator(wxFILTER_NUMERIC
,&v
);
310 WX_PG_DOGETVALIDATOR_EXIT(validator
)
316 wxValidator
* wxIntProperty::DoGetValidator() const
318 return GetClassValidator();
321 // -----------------------------------------------------------------------
323 // -----------------------------------------------------------------------
326 #define wxPG_UINT_TEMPLATE_MAX 8
328 static const wxChar
* gs_uintTemplates32
[wxPG_UINT_TEMPLATE_MAX
] = {
329 wxT("%x"),wxT("0x%x"),wxT("$%x"),
330 wxT("%X"),wxT("0x%X"),wxT("$%X"),
334 static const wxChar
* gs_uintTemplates64
[wxPG_UINT_TEMPLATE_MAX
] = {
335 wxT("%") wxLongLongFmtSpec
wxT("x"),
336 wxT("0x%") wxLongLongFmtSpec
wxT("x"),
337 wxT("$%") wxLongLongFmtSpec
wxT("x"),
338 wxT("%") wxLongLongFmtSpec
wxT("X"),
339 wxT("0x%") wxLongLongFmtSpec
wxT("X"),
340 wxT("$%") wxLongLongFmtSpec
wxT("X"),
341 wxT("%") wxLongLongFmtSpec
wxT("u"),
342 wxT("%") wxLongLongFmtSpec
wxT("o")
345 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty
,wxPGProperty
,
346 long,unsigned long,TextCtrl
)
348 void wxUIntProperty::Init()
350 m_base
= 6; // This is magic number for dec base (must be same as in setattribute)
352 m_prefix
= wxPG_PREFIX_NONE
;
355 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
,
356 unsigned long value
) : wxPGProperty(label
,name
)
359 SetValue((long)value
);
362 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
,
363 const wxULongLong
& value
) : wxPGProperty(label
,name
)
366 SetValue(wxULongLongToVariant(value
));
369 wxUIntProperty::~wxUIntProperty() { }
371 wxString
wxUIntProperty::GetValueAsString( int ) const
373 size_t index
= m_base
+ m_prefix
;
374 if ( index
>= wxPG_UINT_TEMPLATE_MAX
)
375 index
= wxPG_BASE_DEC
;
377 if ( wxPGIsVariantType(m_value
, long) )
378 return wxString::Format(gs_uintTemplates32
[index
],(unsigned long)m_value
.GetLong());
380 return wxString::Format(gs_uintTemplates64
[index
],wxULongLongFromVariant(m_value
).GetValue());
383 bool wxUIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const
385 //long unsigned value32 = 0;
386 bool isPrevLong
= wxPGIsVariantType(variant
, long);
388 if ( text
.length() == 0 )
395 if ( text
[0] == wxS('$') )
398 wxULongLong_t value64
= 0;
399 wxString s
= text
.substr(start
, text
.length() - start
);
401 if ( s
.ToULongLong(&value64
, (unsigned int)m_realBase
) )
403 if ( value64
>= LONG_MAX
)
405 wxULongLong
* _m_value64
= &wxULongLongFromVariant(m_value
);
406 if ( isPrevLong
|| !_m_value64
|| _m_value64
->GetValue() != value64
)
408 variant
= wxULongLongToVariant(value64
);
414 unsigned long value32
= wxLongLong(value64
).GetLo();
415 if ( !isPrevLong
|| m_value
.GetLong() != (long)value32
)
417 variant
= (long)value32
;
426 bool wxUIntProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
428 if ( m_value
!= (long)number
)
430 variant
= (long)number
;
437 #define wxUINT64_MAX ULLONG_MAX
438 #define wxUINT64_MIN wxULL(0)
440 #define wxUINT64_MAX wxULL(0xFFFFFFFFFFFFFFFF)
441 #define wxUINT64_MIN wxULL(0)
444 bool wxUIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
448 if ( wxPGVariantToULongLong(value
, &ll
) )
450 wxULongLong_t min
= wxUINT64_MIN
;
451 wxULongLong_t max
= wxUINT64_MAX
;
454 variant
= GetAttribute(wxPGGlobalVars
->m_strMin
);
455 if ( !variant
.IsNull() )
457 wxPGVariantToULongLong(variant
, &min
);
460 validationInfo
.m_failureMessage
= wxString::Format(_("Value must be %llu or higher"),min
);
464 variant
= GetAttribute(wxPGGlobalVars
->m_strMax
);
465 if ( !variant
.IsNull() )
467 wxPGVariantToULongLong(variant
, &max
);
470 validationInfo
.m_failureMessage
= wxString::Format(_("Value must be %llu or less"),max
);
478 bool wxUIntProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
480 if ( name
== wxPG_UINT_BASE
)
482 int val
= value
.GetLong();
484 m_realBase
= (wxByte
) val
;
485 if ( m_realBase
> 16 )
489 // Translate logical base to a template array index
491 if ( val
== wxPG_BASE_HEX
)
493 else if ( val
== wxPG_BASE_DEC
)
495 else if ( val
== wxPG_BASE_HEXL
)
499 else if ( name
== wxPG_UINT_PREFIX
)
501 m_prefix
= (wxByte
) value
.GetLong();
507 // -----------------------------------------------------------------------
509 // -----------------------------------------------------------------------
511 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty
,wxPGProperty
,
512 double,double,TextCtrl
)
514 wxFloatProperty::wxFloatProperty( const wxString
& label
,
515 const wxString
& name
,
517 : wxPGProperty(label
,name
)
523 wxFloatProperty::~wxFloatProperty() { }
525 // This helper method provides standard way for floating point-using
526 // properties to convert values to string.
527 void wxPropertyGrid::DoubleToString(wxString
& target
,
531 wxString
* precTemplate
)
533 if ( precision
>= 0 )
537 precTemplate
= &text1
;
539 if ( !precTemplate
->length() )
541 *precTemplate
= wxS("%.");
542 *precTemplate
<< wxString::Format( wxS("%i"), precision
);
543 *precTemplate
<< wxS('f');
546 target
.Printf( precTemplate
->c_str(), value
);
550 target
.Printf( wxS("%f"), value
);
553 if ( removeZeroes
&& precision
!= 0 && target
.length() )
555 // Remove excess zeroes (do not remove this code just yet,
556 // since sprintf can't do the same consistently across platforms).
557 wxString::const_iterator i
= target
.end() - 1;
558 size_t new_len
= target
.length() - 1;
560 for ( ; i
!= target
.begin(); i
-- )
562 if ( *i
!= wxS('0') )
567 wxChar cur_char
= *i
;
568 if ( cur_char
!= wxS('.') && cur_char
!= wxS(',') )
571 if ( new_len
!= target
.length() )
572 target
.resize(new_len
);
576 wxString
wxFloatProperty::GetValueAsString( int argFlags
) const
579 if ( !m_value
.IsNull() )
581 wxPropertyGrid::DoubleToString(text
,
584 !(argFlags
& wxPG_FULL_VALUE
),
590 bool wxFloatProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
595 if ( text
.length() == 0 )
601 bool res
= text
.ToDouble(&value
);
604 if ( m_value
!= value
)
610 else if ( argFlags
& wxPG_REPORT_ERROR
)
616 bool wxFloatProperty::DoValidation( const wxPGProperty
* property
, double& value
, wxPGValidationInfo
* pValidationInfo
, int mode
)
619 double min
= (double)wxINT64_MIN
;
620 double max
= (double)wxINT64_MAX
;
625 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
);
626 if ( !variant
.IsNull() )
628 wxPGVariantToDouble(variant
, &min
);
632 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
);
633 if ( !variant
.IsNull() )
635 wxPGVariantToDouble(variant
, &max
);
643 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
644 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %f or higher"),min
);
645 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
648 value
= max
- (min
- value
);
655 wxPGVariantToDouble(variant
, &max
);
658 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
659 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %f or less"),max
);
660 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
663 value
= min
+ (value
- max
);
670 bool wxFloatProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
673 if ( wxPGVariantToDouble(value
, &fpv
) )
674 return DoValidation(this, fpv
, &validationInfo
, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
);
678 bool wxFloatProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
680 if ( name
== wxPG_FLOAT_PRECISION
)
682 m_precision
= value
.GetLong();
688 wxValidator
* wxFloatProperty::DoGetValidator() const
690 return wxIntProperty::GetClassValidator();
693 // -----------------------------------------------------------------------
695 // -----------------------------------------------------------------------
697 // We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since
698 // there is a custom GetEditorClass.
700 IMPLEMENT_DYNAMIC_CLASS(wxBoolProperty
, wxPGProperty
)
702 const wxPGEditor
* wxBoolProperty::DoGetEditorClass() const
704 // Select correct editor control.
705 #if wxPG_INCLUDE_CHECKBOX
706 if ( !(m_flags
& wxPG_PROP_USE_CHECKBOX
) )
707 return wxPG_EDITOR(Choice
);
708 return wxPG_EDITOR(CheckBox
);
710 return wxPG_EDITOR(Choice
);
714 wxBoolProperty::wxBoolProperty( const wxString
& label
, const wxString
& name
, bool value
) :
715 wxPGProperty(label
,name
)
717 SetValue(wxPGVariant_Bool(value
));
719 m_flags
|= wxPG_PROP_USE_DCC
;
722 wxBoolProperty::~wxBoolProperty() { }
724 wxString
wxBoolProperty::GetValueAsString( int argFlags
) const
726 bool value
= m_value
.GetBool();
728 // As a fragment of composite string value,
729 // make it a little more readable.
730 if ( argFlags
& wxPG_COMPOSITE_FRAGMENT
)
738 if ( argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
)
739 return wxEmptyString
;
741 const wxChar
* notFmt
;
742 if ( wxPGGlobalVars
->m_autoGetTranslation
)
743 notFmt
= _("Not %s");
745 notFmt
= wxT("Not %s");
747 return wxString::Format(notFmt
,m_label
.c_str());
751 if ( !(argFlags
& wxPG_FULL_VALUE
) )
753 return wxPGGlobalVars
->m_boolChoices
[value
?1:0].GetText();
758 if (value
) text
= wxS("true");
759 else text
= wxS("false");
764 int wxBoolProperty::GetChoiceInfo( wxPGChoiceInfo
* choiceinfo
)
766 if ( IsValueUnspecified() )
770 choiceinfo
->m_choices
= &wxPGGlobalVars
->m_boolChoices
;
771 return m_value
.GetBool()?1:0;
774 bool wxBoolProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const
777 if ( text
.CmpNoCase(wxPGGlobalVars
->m_boolChoices
[1].GetText()) == 0 ||
778 text
.CmpNoCase(wxS("true")) == 0 ||
779 text
.CmpNoCase(m_label
) == 0 )
782 if ( text
.length() == 0 )
788 bool oldValue
= m_value
.GetBool();
790 if ( (oldValue
&& !value
) || (!oldValue
&& value
) )
792 variant
= wxPGVariant_Bool(value
);
798 bool wxBoolProperty::IntToValue( wxVariant
& variant
, int value
, int ) const
800 bool boolValue
= value
? true : false;
801 bool oldValue
= m_value
.GetBool();
803 if ( oldValue
!= boolValue
)
805 variant
= wxPGVariant_Bool(boolValue
);
811 bool wxBoolProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
813 #if wxPG_INCLUDE_CHECKBOX
814 if ( name
== wxPG_BOOL_USE_CHECKBOX
)
816 int ival
= wxPGVariantToInt(value
);
818 m_flags
|= wxPG_PROP_USE_CHECKBOX
;
820 m_flags
&= ~(wxPG_PROP_USE_CHECKBOX
);
824 if ( name
== wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING
)
826 int ival
= wxPGVariantToInt(value
);
828 m_flags
|= wxPG_PROP_USE_DCC
;
830 m_flags
&= ~(wxPG_PROP_USE_DCC
);
836 // -----------------------------------------------------------------------
837 // wxBaseEnumProperty
838 // -----------------------------------------------------------------------
840 int wxBaseEnumProperty::ms_nextIndex
= -2;
842 wxBaseEnumProperty::wxBaseEnumProperty( const wxString
& label
, const wxString
& name
)
843 : wxPGProperty(label
,name
)
845 m_value
= wxPGVariant_Zero
;
848 /** If has values array, then returns number at index with value -
849 otherwise just returns the value.
851 int wxBaseEnumProperty::GetIndexForValue( int value
) const
856 void wxBaseEnumProperty::OnSetValue()
858 if ( wxPGIsVariantType(m_value
, long) )
859 ValueFromInt_( m_value
, m_value
.GetLong(), wxPG_FULL_VALUE
);
860 else if ( wxPGIsVariantType(m_value
, string
) )
861 ValueFromString_( m_value
, m_value
.GetString(), 0 );
865 if ( ms_nextIndex
!= -2 )
867 m_index
= ms_nextIndex
;
872 bool wxBaseEnumProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
874 // Make sure string value is in the list,
875 // unless property has string as preferred value type
876 // To reduce code size, use conversion here as well
877 if ( wxPGIsVariantType(value
, string
) &&
878 !this->IsKindOf(CLASSINFO(wxEditEnumProperty
)) )
879 return ValueFromString_( value
, value
.GetString(), wxPG_PROPERTY_SPECIFIC
);
884 wxString
wxBaseEnumProperty::GetValueAsString( int ) const
886 if ( wxPGIsVariantType(m_value
, string
) )
887 return m_value
.GetString();
892 const wxString
* pstr
= GetEntry( m_index
, &unusedVal
);
897 return wxEmptyString
;
900 bool wxBaseEnumProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
902 return ValueFromString_( variant
, text
, argFlags
);
905 bool wxBaseEnumProperty::IntToValue( wxVariant
& variant
, int intVal
, int argFlags
) const
907 return ValueFromInt_( variant
, intVal
, argFlags
);
910 bool wxBaseEnumProperty::ValueFromString_( wxVariant
& value
, const wxString
& text
, int argFlags
) const
913 const wxString
* entryLabel
;
918 entryLabel
= GetEntry(i
, &entryValue
);
921 if ( text
.CmpNoCase(*entryLabel
) == 0 )
924 useValue
= (long)entryValue
;
929 entryLabel
= GetEntry(i
, &entryValue
);
934 bool isEdit
= this->IsKindOf(CLASSINFO(wxEditEnumProperty
));
936 // If text not any of the choices, store as text instead
937 // (but only if we are wxEditEnumProperty)
938 if ( useIndex
== -1 &&
939 (!wxPGIsVariantType(m_value
, string
) || (m_value
.GetString() != text
)) &&
945 int setAsNextIndex
= -2;
952 else if ( m_index
!= useIndex
)
954 if ( useIndex
!= -1 )
956 setAsNextIndex
= useIndex
;
957 value
= (long)useValue
;
962 value
= wxPGVariant_MinusOne
;
966 if ( setAsNextIndex
!= -2 )
968 // If wxPG_PROPERTY_SPECIFIC is set, then this is done for
969 // validation purposes only, and index must not be changed
970 if ( !(argFlags
& wxPG_PROPERTY_SPECIFIC
) )
971 ms_nextIndex
= setAsNextIndex
;
973 if ( isEdit
|| setAsNextIndex
!= -1 )
981 bool wxBaseEnumProperty::ValueFromInt_( wxVariant
& variant
, int intVal
, int argFlags
) const
983 // If wxPG_FULL_VALUE is *not* in argFlags, then intVal is index from combo box.
987 if ( argFlags
& wxPG_FULL_VALUE
)
989 ms_nextIndex
= GetIndexForValue( intVal
);
993 if ( m_index
!= intVal
)
995 ms_nextIndex
= intVal
;
999 if ( ms_nextIndex
!= -2 )
1001 if ( !(argFlags
& wxPG_FULL_VALUE
) )
1002 GetEntry(intVal
, &intVal
);
1004 variant
= (long)intVal
;
1012 void wxBaseEnumProperty::SetIndex( int index
)
1018 int wxBaseEnumProperty::GetIndex() const
1020 if ( ms_nextIndex
!= -2 )
1021 return ms_nextIndex
;
1025 // -----------------------------------------------------------------------
1027 // -----------------------------------------------------------------------
1029 IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty
, wxPGProperty
)
1031 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty
,long,Choice
)
1033 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1034 const long* values
, int value
) : wxBaseEnumProperty(label
,name
)
1040 m_choices
.Add(labels
,values
);
1042 if ( GetItemCount() )
1043 SetValue( (long)value
);
1047 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1048 const long* values
, wxPGChoices
* choicesCache
, int value
)
1049 : wxBaseEnumProperty(label
,name
)
1053 wxASSERT( choicesCache
);
1055 if ( choicesCache
->IsOk() )
1057 m_choices
.Assign( *choicesCache
);
1058 m_value
= wxPGVariant_Zero
;
1062 m_choices
.Add(labels
,values
);
1064 if ( GetItemCount() )
1065 SetValue( (long)value
);
1069 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
,
1070 const wxArrayString
& labels
, const wxArrayInt
& values
, int value
) : wxBaseEnumProperty(label
,name
)
1074 if ( &labels
&& labels
.size() )
1076 m_choices
.Set(labels
, values
);
1078 if ( GetItemCount() )
1079 SetValue( (long)value
);
1083 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
,
1084 wxPGChoices
& choices
, int value
)
1085 : wxBaseEnumProperty(label
,name
)
1087 m_choices
.Assign( choices
);
1089 if ( GetItemCount() )
1090 SetValue( (long)value
);
1093 int wxEnumProperty::GetIndexForValue( int value
) const
1095 if ( !m_choices
.IsOk() )
1098 if ( m_choices
.HasValues() )
1100 int intVal
= m_choices
.Index(value
);
1108 wxEnumProperty::~wxEnumProperty ()
1112 const wxString
* wxEnumProperty::GetEntry( size_t index
, int* pvalue
) const
1114 if ( m_choices
.IsOk() && index
< m_choices
.GetCount() )
1116 int value
= (int)index
;
1117 if ( m_choices
.HasValue(index
) )
1118 value
= m_choices
.GetValue(index
);
1123 return &m_choices
.GetLabel(index
);
1125 return (const wxString
*) NULL
;
1128 int wxEnumProperty::GetChoiceInfo( wxPGChoiceInfo
* choiceinfo
)
1131 choiceinfo
->m_choices
= &m_choices
;
1133 if ( !m_choices
.IsOk() )
1139 // -----------------------------------------------------------------------
1140 // wxEditEnumProperty
1141 // -----------------------------------------------------------------------
1143 IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty
, wxPGProperty
)
1145 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty
,wxString
,ComboBox
)
1147 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1148 const long* values
, const wxString
& value
)
1149 : wxEnumProperty(label
,name
,labels
,values
,0)
1154 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1155 const long* values
, wxPGChoices
* choicesCache
, const wxString
& value
)
1156 : wxEnumProperty(label
,name
,labels
,values
,choicesCache
,0)
1161 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
,
1162 const wxArrayString
& labels
, const wxArrayInt
& values
, const wxString
& value
)
1163 : wxEnumProperty(label
,name
,labels
,values
,0)
1168 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
,
1169 wxPGChoices
& choices
, const wxString
& value
)
1170 : wxEnumProperty(label
,name
,choices
,0)
1175 wxEditEnumProperty::~wxEditEnumProperty()
1179 // -----------------------------------------------------------------------
1181 // -----------------------------------------------------------------------
1183 IMPLEMENT_DYNAMIC_CLASS(wxFlagsProperty
,wxPGProperty
)
1185 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty
,long,TextCtrl
)
1187 void wxFlagsProperty::Init()
1189 SetFlag(wxPG_PROP_AGGREGATE
); // This is must be done here to support flag props
1190 // with inital zero children.
1192 long value
= m_value
;
1195 // Generate children
1199 unsigned int prevChildCount
= m_children
.GetCount();
1202 if ( prevChildCount
)
1204 wxPropertyGridPageState
* state
= GetParentState();
1206 // State safety check (it may be NULL in immediate parent)
1211 wxPGProperty
* selected
= state
->GetSelection();
1214 if ( selected
->GetParent() == this )
1215 oldSel
= selected
->GetArrIndex();
1216 else if ( selected
== this )
1220 state
->DoClearSelection();
1223 // Delete old children
1224 for ( i
=0; i
<prevChildCount
; i
++ )
1225 delete ( (wxPGProperty
*) m_children
[i
] );
1229 if ( m_choices
.IsOk() )
1231 const wxPGChoices
& choices
= m_choices
;
1233 for ( i
=0; i
<GetItemCount(); i
++ )
1236 if ( choices
.HasValue(i
) )
1237 child_val
= ( value
& choices
.GetValue(i
) )?true:false;
1239 child_val
= ( value
& (1<<i
) )?true:false;
1241 wxPGProperty
* boolProp
;
1244 if ( wxPGGlobalVars
->m_autoGetTranslation
)
1246 boolProp
= new wxBoolProperty( ::wxGetTranslation( GetLabel(i
) ), wxEmptyString
, child_val
);
1251 boolProp
= new wxBoolProperty( GetLabel(i
), wxEmptyString
, child_val
);
1256 m_oldChoicesData
= m_choices
.GetDataPtr();
1259 m_oldValue
= m_value
;
1261 if ( prevChildCount
)
1262 SubPropsChanged(oldSel
);
1265 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1266 const wxChar
** labels
, const long* values
, long value
) : wxPGProperty(label
,name
)
1268 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1272 m_choices
.Set(labels
,values
);
1274 wxASSERT( GetItemCount() );
1280 m_value
= wxPGVariant_Zero
;
1284 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1285 const wxArrayString
& labels
, const wxArrayInt
& values
, int value
)
1286 : wxPGProperty(label
,name
)
1288 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1290 if ( &labels
&& labels
.size() )
1292 m_choices
.Set(labels
,values
);
1294 wxASSERT( GetItemCount() );
1296 SetValue( (long)value
);
1300 m_value
= wxPGVariant_Zero
;
1304 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1305 wxPGChoices
& choices
, long value
)
1306 : wxPGProperty(label
,name
)
1308 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1310 if ( choices
.IsOk() )
1312 m_choices
.Assign(choices
);
1314 wxASSERT( GetItemCount() );
1320 m_value
= wxPGVariant_Zero
;
1324 wxFlagsProperty::~wxFlagsProperty()
1328 void wxFlagsProperty::OnSetValue()
1330 if ( !m_choices
.IsOk() || !GetItemCount() )
1332 m_value
= wxPGVariant_Zero
;
1336 long val
= m_value
.GetLong();
1340 // normalize the value (i.e. remove extra flags)
1342 const wxPGChoices
& choices
= m_choices
;
1343 for ( i
= 0; i
< GetItemCount(); i
++ )
1345 if ( choices
.HasValue(i
) )
1346 fullFlags
|= choices
.GetValue(i
);
1348 fullFlags
|= (1<<i
);
1355 // Need to (re)init now?
1356 if ( GetChildCount() != GetItemCount() ||
1357 m_choices
.GetDataPtr() != m_oldChoicesData
)
1363 long newFlags
= m_value
;
1365 if ( newFlags
!= m_oldValue
)
1367 // Set child modified states
1369 const wxPGChoices
& choices
= m_choices
;
1370 for ( i
= 0; i
<GetItemCount(); i
++ )
1374 if ( choices
.HasValue(i
) )
1375 flag
= choices
.GetValue(i
);
1379 if ( (newFlags
& flag
) != (m_oldValue
& flag
) )
1380 Item(i
)->SetFlag( wxPG_PROP_MODIFIED
);
1383 m_oldValue
= newFlags
;
1387 wxString
wxFlagsProperty::GetValueAsString( int ) const
1391 if ( !m_choices
.IsOk() )
1394 long flags
= m_value
;
1396 const wxPGChoices
& choices
= m_choices
;
1398 for ( i
= 0; i
< GetItemCount(); i
++ )
1401 if ( choices
.HasValue(i
) )
1402 doAdd
= ( flags
& choices
.GetValue(i
) );
1404 doAdd
= ( flags
& (1<<i
) );
1408 text
+= choices
.GetLabel(i
);
1413 // remove last comma
1414 if ( text
.Len() > 1 )
1415 text
.Truncate ( text
.Len() - 2 );
1420 // Translate string into flag tokens
1421 bool wxFlagsProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
1423 if ( !m_choices
.IsOk() )
1427 long oldValue
= m_value
;
1429 // semicolons are no longer valid delimeters
1430 WX_PG_TOKENIZER1_BEGIN(text
,wxS(','))
1432 if ( token
.length() )
1434 // Determine which one it is
1435 long bit
= IdToBit( token
);
1448 WX_PG_TOKENIZER1_END()
1452 if ( newFlags
!= oldValue
)
1458 // Converts string id to a relevant bit.
1459 long wxFlagsProperty::IdToBit( const wxString
& id
) const
1462 for ( i
= 0; i
< GetItemCount(); i
++ )
1464 if ( id
== GetLabel(i
) )
1466 if ( m_choices
.HasValue(i
) )
1467 return m_choices
.GetValue(i
);
1474 void wxFlagsProperty::RefreshChildren()
1476 if ( !m_choices
.IsOk() || !GetChildCount() ) return;
1478 int flags
= m_value
.GetLong();
1480 const wxPGChoices
& choices
= m_choices
;
1482 for ( i
= 0; i
< GetItemCount(); i
++ )
1486 if ( choices
.HasValue(i
) )
1487 flag
= choices
.GetValue(i
);
1491 long subVal
= flags
& flag
;
1492 wxPGProperty
* p
= Item(i
);
1494 if ( subVal
!= (m_oldValue
& flag
) )
1495 p
->SetFlag( wxPG_PROP_MODIFIED
);
1497 p
->SetValue( subVal
?true:false );
1503 void wxFlagsProperty::ChildChanged( wxVariant
& thisValue
, int childIndex
, wxVariant
& childValue
) const
1505 long oldValue
= thisValue
.GetLong();
1506 long val
= childValue
.GetLong();
1507 unsigned long vi
= (1<<childIndex
);
1508 if ( m_choices
.HasValue(childIndex
) ) vi
= m_choices
.GetValue(childIndex
);
1510 thisValue
= (long)(oldValue
| vi
);
1512 thisValue
= (long)(oldValue
& ~(vi
));
1515 int wxFlagsProperty::GetChoiceInfo( wxPGChoiceInfo
* choiceinfo
)
1518 choiceinfo
->m_choices
= &m_choices
;
1522 // -----------------------------------------------------------------------
1524 // -----------------------------------------------------------------------
1526 WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxDirProperty
,wxLongStringProperty
,const wxString
&)
1528 wxDirProperty::wxDirProperty( const wxString
& name
, const wxString
& label
, const wxString
& value
)
1529 : wxLongStringProperty(name
,label
,value
)
1531 m_flags
|= wxPG_NO_ESCAPE
;
1533 wxDirProperty::~wxDirProperty() { }
1535 wxValidator
* wxDirProperty::DoGetValidator() const
1537 return wxFileProperty::GetClassValidator();
1540 bool wxDirProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value
)
1542 wxSize
dlg_sz(300,400);
1544 wxDirDialog
dlg( propGrid
,
1545 m_dlgMessage
.length() ? m_dlgMessage
: wxString(_("Choose a directory:")),
1548 #if !wxPG_SMALL_SCREEN
1549 propGrid
->GetGoodEditorDialogPosition(this,dlg_sz
),
1556 if ( dlg
.ShowModal() == wxID_OK
)
1558 value
= dlg
.GetPath();
1564 bool wxDirProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1566 if ( name
== wxPG_DIR_DIALOG_MESSAGE
)
1568 m_dlgMessage
= value
.GetString();
1574 // -----------------------------------------------------------------------
1575 // wxPGFileDialogAdapter
1576 // -----------------------------------------------------------------------
1578 bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property
)
1580 wxFileProperty
* fileProp
= NULL
;
1584 if ( property
->IsKindOf(CLASSINFO(wxFileProperty
)) )
1586 fileProp
= ((wxFileProperty
*)property
);
1587 path
= fileProp
->m_filename
.GetPath();
1588 indFilter
= fileProp
->m_indFilter
;
1590 if ( !path
.length() && fileProp
->m_basePath
.length() )
1591 path
= fileProp
->m_basePath
;
1595 wxFileName
fn(property
->GetValue().GetString());
1596 path
= fn
.GetPath();
1599 wxFileDialog
dlg( propGrid
->GetPanel(),
1600 property
->GetAttribute(wxS("DialogTitle"), _("Choose a file")),
1601 property
->GetAttribute(wxS("InitialPath"), path
),
1603 property
->GetAttribute(wxPG_FILE_WILDCARD
, _("All files (*.*)|*.*")),
1605 wxDefaultPosition
);
1607 if ( indFilter
>= 0 )
1608 dlg
.SetFilterIndex( indFilter
);
1610 if ( dlg
.ShowModal() == wxID_OK
)
1613 fileProp
->m_indFilter
= dlg
.GetFilterIndex();
1614 SetValue( dlg
.GetPath() );
1620 // -----------------------------------------------------------------------
1622 // -----------------------------------------------------------------------
1624 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty
,wxPGProperty
,
1625 wxString
,const wxString
&,TextCtrlAndButton
)
1627 wxFileProperty::wxFileProperty( const wxString
& label
, const wxString
& name
,
1628 const wxString
& value
) : wxPGProperty(label
,name
)
1630 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1632 SetAttribute( wxPG_FILE_WILDCARD
, _("All files (*.*)|*.*") );
1637 wxFileProperty::~wxFileProperty() {}
1639 #if wxUSE_VALIDATORS
1641 wxValidator
* wxFileProperty::GetClassValidator()
1643 WX_PG_DOGETVALIDATOR_ENTRY()
1645 // Atleast wxPython 2.6.2.1 required that the string argument is given
1647 wxTextValidator
* validator
= new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST
,&v
);
1649 wxArrayString exChars
;
1650 exChars
.Add(wxS("?"));
1651 exChars
.Add(wxS("*"));
1652 exChars
.Add(wxS("|"));
1653 exChars
.Add(wxS("<"));
1654 exChars
.Add(wxS(">"));
1655 exChars
.Add(wxS("\""));
1657 validator
->SetExcludes(exChars
);
1659 WX_PG_DOGETVALIDATOR_EXIT(validator
)
1662 wxValidator
* wxFileProperty::DoGetValidator() const
1664 return GetClassValidator();
1669 void wxFileProperty::OnSetValue()
1671 const wxString
& fnstr
= m_value
.GetString();
1675 if ( !m_filename
.HasName() )
1677 m_value
= wxPGVariant_EmptyString
;
1681 // Find index for extension.
1682 if ( m_indFilter
< 0 && fnstr
.length() )
1684 wxString ext
= m_filename
.GetExt();
1687 size_t len
= m_wildcard
.length();
1689 pos
= m_wildcard
.find(wxS("|"), pos
);
1690 while ( pos
!= wxString::npos
&& pos
< (len
-3) )
1692 size_t ext_begin
= pos
+ 3;
1694 pos
= m_wildcard
.find(wxS("|"), ext_begin
);
1695 if ( pos
== wxString::npos
)
1697 wxString found_ext
= m_wildcard
.substr(ext_begin
, pos
-ext_begin
);
1699 if ( found_ext
.length() > 0 )
1701 if ( found_ext
[0] == wxS('*') )
1703 m_indFilter
= curind
;
1706 if ( ext
.CmpNoCase(found_ext
) == 0 )
1708 m_indFilter
= curind
;
1714 pos
= m_wildcard
.find(wxS("|"), pos
+1);
1721 wxString
wxFileProperty::GetValueAsString( int argFlags
) const
1723 // Always return empty string when name component is empty
1724 wxString fullName
= m_filename
.GetFullName();
1725 if ( !fullName
.length() )
1728 if ( argFlags
& wxPG_FULL_VALUE
)
1730 return m_filename
.GetFullPath();
1732 else if ( m_flags
& wxPG_PROP_SHOW_FULL_FILENAME
)
1734 if ( m_basePath
.Length() )
1736 wxFileName
fn2(m_filename
);
1737 fn2
.MakeRelativeTo(m_basePath
);
1738 return fn2
.GetFullPath();
1740 return m_filename
.GetFullPath();
1743 return m_filename
.GetFullName();
1746 wxPGEditorDialogAdapter
* wxFileProperty::GetEditorDialog() const
1748 return new wxPGFileDialogAdapter();
1751 bool wxFileProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
1753 if ( (m_flags
& wxPG_PROP_SHOW_FULL_FILENAME
) || (argFlags
& wxPG_FULL_VALUE
) )
1755 if ( m_filename
!= text
)
1763 if ( m_filename
.GetFullName() != text
)
1765 wxFileName fn
= m_filename
;
1766 fn
.SetFullName(text
);
1767 variant
= fn
.GetFullPath();
1775 bool wxFileProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1777 // Return false on some occasions to make sure those attribs will get
1778 // stored in m_attributes.
1779 if ( name
== wxPG_FILE_SHOW_FULL_PATH
)
1781 if ( wxPGVariantToInt(value
) )
1782 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1784 m_flags
&= ~(wxPG_PROP_SHOW_FULL_FILENAME
);
1787 else if ( name
== wxPG_FILE_WILDCARD
)
1789 m_wildcard
= value
.GetString();
1791 else if ( name
== wxPG_FILE_SHOW_RELATIVE_PATH
)
1793 m_basePath
= value
.GetString();
1795 // Make sure wxPG_FILE_SHOW_FULL_PATH is also set
1796 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1798 else if ( name
== wxPG_FILE_INITIAL_PATH
)
1800 m_initialPath
= value
.GetString();
1803 else if ( name
== wxPG_FILE_DIALOG_TITLE
)
1805 m_dlgTitle
= value
.GetString();
1811 // -----------------------------------------------------------------------
1812 // wxPGLongStringDialogAdapter
1813 // -----------------------------------------------------------------------
1815 bool wxPGLongStringDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property
)
1817 wxString val1
= property
->GetValueAsString(0);
1818 wxString val_orig
= val1
;
1821 if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) )
1822 wxPropertyGrid::ExpandEscapeSequences(value
, val1
);
1824 value
= wxString(val1
);
1826 // Run editor dialog.
1827 if ( wxLongStringProperty::DisplayEditorDialog(property
, propGrid
, value
) )
1829 if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) )
1830 wxPropertyGrid::CreateEscapeSequences(val1
,value
);
1834 if ( val1
!= val_orig
)
1843 // -----------------------------------------------------------------------
1844 // wxLongStringProperty
1845 // -----------------------------------------------------------------------
1847 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty
,wxPGProperty
,
1848 wxString
,const wxString
&,TextCtrlAndButton
)
1850 wxLongStringProperty::wxLongStringProperty( const wxString
& label
, const wxString
& name
,
1851 const wxString
& value
) : wxPGProperty(label
,name
)
1856 wxLongStringProperty::~wxLongStringProperty() {}
1858 wxString
wxLongStringProperty::GetValueAsString( int ) const
1863 bool wxLongStringProperty::OnEvent( wxPropertyGrid
* propGrid
, wxWindow
* WXUNUSED(primary
),
1866 if ( propGrid
->IsMainButtonEvent(event
) )
1869 PrepareValueForDialogEditing(propGrid
);
1871 wxString val1
= GetValueAsString(0);
1872 wxString val_orig
= val1
;
1875 if ( !(m_flags
& wxPG_PROP_NO_ESCAPE
) )
1876 wxPropertyGrid::ExpandEscapeSequences(value
,val1
);
1878 value
= wxString(val1
);
1880 // Run editor dialog.
1881 if ( OnButtonClick(propGrid
,value
) )
1883 if ( !(m_flags
& wxPG_PROP_NO_ESCAPE
) )
1884 wxPropertyGrid::CreateEscapeSequences(val1
,value
);
1888 if ( val1
!= val_orig
)
1890 SetValueInEvent( val1
);
1898 bool wxLongStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value
)
1900 return DisplayEditorDialog(this, propGrid
, value
);
1903 bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty
* prop
, wxPropertyGrid
* propGrid
, wxString
& value
)
1906 // launch editor dialog
1907 wxDialog
* dlg
= new wxDialog(propGrid
,-1,prop
->GetLabel(),wxDefaultPosition
,wxDefaultSize
,
1908 wxDEFAULT_DIALOG_STYLE
|wxRESIZE_BORDER
|wxCLIP_CHILDREN
);
1910 dlg
->SetFont(propGrid
->GetFont()); // To allow entering chars of the same set as the propGrid
1912 // Multi-line text editor dialog.
1913 #if !wxPG_SMALL_SCREEN
1914 const int spacing
= 8;
1916 const int spacing
= 4;
1918 wxBoxSizer
* topsizer
= new wxBoxSizer( wxVERTICAL
);
1919 wxBoxSizer
* rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
1920 wxTextCtrl
* ed
= new wxTextCtrl(dlg
,11,value
,
1921 wxDefaultPosition
,wxDefaultSize
,wxTE_MULTILINE
);
1923 rowsizer
->Add( ed
, 1, wxEXPAND
|wxALL
, spacing
);
1924 topsizer
->Add( rowsizer
, 1, wxEXPAND
, 0 );
1925 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
1926 const int but_sz_flags
=
1927 wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxBOTTOM
|wxLEFT
|wxRIGHT
;
1928 rowsizer
->Add( new wxButton(dlg
,wxID_OK
,_("Ok")),
1929 0, but_sz_flags
, spacing
);
1930 rowsizer
->Add( new wxButton(dlg
,wxID_CANCEL
,_("Cancel")),
1931 0, but_sz_flags
, spacing
);
1932 topsizer
->Add( rowsizer
, 0, wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
, 0 );
1934 dlg
->SetSizer( topsizer
);
1935 topsizer
->SetSizeHints( dlg
);
1937 #if !wxPG_SMALL_SCREEN
1938 dlg
->SetSize(400,300);
1940 dlg
->Move( propGrid
->GetGoodEditorDialogPosition(prop
,dlg
->GetSize()) );
1943 int res
= dlg
->ShowModal();
1945 if ( res
== wxID_OK
)
1947 value
= ed
->GetValue();
1955 bool wxLongStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
1957 if ( m_value
!= text
)
1965 // -----------------------------------------------------------------------
1966 // wxArrayEditorDialog
1967 // -----------------------------------------------------------------------
1969 BEGIN_EVENT_TABLE(wxArrayEditorDialog
, wxDialog
)
1970 EVT_IDLE(wxArrayEditorDialog::OnIdle
)
1971 EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick
)
1972 EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick
)
1973 EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick
)
1974 EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick
)
1975 EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick
)
1976 EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick
)
1977 EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick
)
1978 //EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick)
1981 IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog
, wxDialog
)
1983 #include <wx/statline.h>
1985 // -----------------------------------------------------------------------
1987 void wxArrayEditorDialog::OnIdle(wxIdleEvent
& event
)
1990 // Do control focus detection here.
1993 wxWindow
* focused
= FindFocus();
1995 // This strange focus thing is a workaround for wxGTK wxListBox focus
1997 if ( m_curFocus
== 0 && focused
!= m_edValue
&&
1998 focused
!= m_butAdd
&& focused
!= m_butUpdate
&&
1999 m_lbStrings
->GetSelection() >= 0 )
2001 // ListBox was just focused.
2002 m_butAdd
->Enable(false);
2003 m_butUpdate
->Enable(false);
2004 m_butRemove
->Enable(true);
2005 m_butUp
->Enable(true);
2006 m_butDown
->Enable(true);
2009 else if ( (m_curFocus
== 1 && focused
== m_edValue
) /*|| m_curFocus == 2*/ )
2011 // TextCtrl was just focused.
2012 m_butAdd
->Enable(true);
2013 bool upd_enable
= false;
2014 if ( m_lbStrings
->GetCount() && m_lbStrings
->GetSelection() >= 0 )
2016 m_butUpdate
->Enable(upd_enable
);
2017 m_butRemove
->Enable(false);
2018 m_butUp
->Enable(false);
2019 m_butDown
->Enable(false);
2026 // -----------------------------------------------------------------------
2028 wxArrayEditorDialog::wxArrayEditorDialog()
2034 // -----------------------------------------------------------------------
2036 void wxArrayEditorDialog::Init()
2038 m_custBtText
= (const wxChar
*) NULL
;
2041 // -----------------------------------------------------------------------
2043 wxArrayEditorDialog::wxArrayEditorDialog( wxWindow
*parent
,
2044 const wxString
& message
,
2045 const wxString
& caption
,
2052 Create(parent
,message
,caption
,style
,pos
,sz
);
2055 // -----------------------------------------------------------------------
2057 bool wxArrayEditorDialog::Create( wxWindow
*parent
,
2058 const wxString
& message
,
2059 const wxString
& caption
,
2064 // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION
2065 // FIXME: This should be only a temporary fix.
2067 int useStyle
= wxCAPTION
;
2069 int useStyle
= style
;
2072 bool res
= wxDialog::Create(parent
, wxID_ANY
, caption
, pos
, sz
, useStyle
);
2074 SetFont(parent
->GetFont()); // To allow entering chars of the same set as the propGrid
2076 #if !wxPG_SMALL_SCREEN
2077 const int spacing
= 4;
2079 const int spacing
= 3;
2086 const int but_sz_flags
=
2087 wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxALL
; //wxBOTTOM|wxLEFT|wxRIGHT;
2089 wxBoxSizer
* topsizer
= new wxBoxSizer( wxVERTICAL
);
2092 if ( message
.length() )
2093 topsizer
->Add( new wxStaticText(this,-1,message
),
2094 0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing
);
2097 wxBoxSizer
* rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2098 m_edValue
= new wxTextCtrl(this,21,wxEmptyString
,
2099 wxDefaultPosition
,wxDefaultSize
,wxTE_PROCESS_ENTER
);
2100 wxValidator
* validator
= GetTextCtrlValidator();
2103 m_edValue
->SetValidator( *validator
);
2106 rowsizer
->Add( m_edValue
,
2107 1, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing
);
2110 m_butAdd
= new wxButton(this,22,_("Add"));
2111 rowsizer
->Add( m_butAdd
,
2112 0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxTOP
|wxBOTTOM
|wxRIGHT
, spacing
);
2113 topsizer
->Add( rowsizer
, 0, wxEXPAND
, spacing
);
2116 topsizer
->Add( new wxStaticLine(this,-1),
2117 0, wxEXPAND
|wxBOTTOM
|wxLEFT
|wxRIGHT
, spacing
);
2119 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2122 m_lbStrings
= new wxListBox(this, 24, wxDefaultPosition
, wxDefaultSize
);
2124 for ( i
=0; i
<ArrayGetCount(); i
++ )
2125 m_lbStrings
->Append( ArrayGet(i
) );
2126 rowsizer
->Add( m_lbStrings
, 1, wxEXPAND
|wxRIGHT
, spacing
);
2128 // Manipulator buttons
2129 wxBoxSizer
* colsizer
= new wxBoxSizer( wxVERTICAL
);
2130 m_butCustom
= (wxButton
*) NULL
;
2133 m_butCustom
= new wxButton(this,28,::wxGetTranslation(m_custBtText
));
2134 colsizer
->Add( m_butCustom
,
2135 0, wxALIGN_CENTER
|wxTOP
/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/,
2138 m_butUpdate
= new wxButton(this,27,_("Update"));
2139 colsizer
->Add( m_butUpdate
,
2140 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2141 m_butRemove
= new wxButton(this,23,_("Remove"));
2142 colsizer
->Add( m_butRemove
,
2143 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2144 m_butUp
= new wxButton(this,25,_("Up"));
2145 colsizer
->Add( m_butUp
,
2146 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2147 m_butDown
= new wxButton(this,26,_("Down"));
2148 colsizer
->Add( m_butDown
,
2149 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2150 rowsizer
->Add( colsizer
, 0, 0, spacing
);
2152 topsizer
->Add( rowsizer
, 1, wxLEFT
|wxRIGHT
|wxEXPAND
, spacing
);
2155 topsizer
->Add( new wxStaticLine(this,-1),
2156 0, wxEXPAND
|wxTOP
|wxLEFT
|wxRIGHT
, spacing
);
2159 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2161 const int but_sz_flags =
2162 wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT;
2164 rowsizer
->Add( new wxButton(this,wxID_OK
,_("Ok")),
2165 0, but_sz_flags
, spacing
);
2166 rowsizer
->Add( new wxButton(this,wxID_CANCEL
,_("Cancel")),
2167 0, but_sz_flags
, spacing
);
2168 topsizer
->Add( rowsizer
, 0, wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
, 0 );
2170 m_edValue
->SetFocus();
2172 SetSizer( topsizer
);
2173 topsizer
->SetSizeHints( this );
2175 #if !wxPG_SMALL_SCREEN
2176 if ( sz
.x
== wxDefaultSize
.x
&&
2177 sz
.y
== wxDefaultSize
.y
)
2178 SetSize( wxSize(275,360) );
2186 // -----------------------------------------------------------------------
2188 void wxArrayEditorDialog::OnAddClick(wxCommandEvent
& )
2190 wxString text
= m_edValue
->GetValue();
2191 if ( text
.length() )
2193 if ( ArrayInsert( text
, -1 ) )
2195 m_lbStrings
->Append( text
);
2202 // -----------------------------------------------------------------------
2204 void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent
& )
2206 int index
= m_lbStrings
->GetSelection();
2209 ArrayRemoveAt( index
);
2210 m_lbStrings
->Delete ( index
);
2215 // -----------------------------------------------------------------------
2217 void wxArrayEditorDialog::OnUpClick(wxCommandEvent
& )
2219 int index
= m_lbStrings
->GetSelection();
2222 ArraySwap(index
-1,index
);
2223 /*wxString old_str = m_array[index-1];
2224 wxString new_str = m_array[index];
2225 m_array[index-1] = new_str;
2226 m_array[index] = old_str;*/
2227 m_lbStrings
->SetString ( index
-1, ArrayGet(index
-1) );
2228 m_lbStrings
->SetString ( index
, ArrayGet(index
) );
2229 m_lbStrings
->SetSelection ( index
-1 );
2234 // -----------------------------------------------------------------------
2236 void wxArrayEditorDialog::OnDownClick(wxCommandEvent
& )
2238 int index
= m_lbStrings
->GetSelection();
2239 int lastStringIndex
= ((int) m_lbStrings
->GetCount()) - 1;
2240 if ( index
>= 0 && index
< lastStringIndex
)
2242 ArraySwap(index
,index
+1);
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::OnUpdateClick(wxCommandEvent
& )
2258 int index
= m_lbStrings
->GetSelection();
2261 wxString str
= m_edValue
->GetValue();
2262 if ( ArraySet(index
,str
) )
2264 m_lbStrings
->SetString ( index
, str
);
2265 //m_array[index] = str;
2271 // -----------------------------------------------------------------------
2273 void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent
& )
2275 int index
= m_lbStrings
->GetSelection();
2278 m_edValue
->SetValue( m_lbStrings
->GetString(index
) );
2282 // -----------------------------------------------------------------------
2283 // wxPGArrayStringEditorDialog
2284 // -----------------------------------------------------------------------
2286 IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog
, wxArrayEditorDialog
)
2288 BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog
, wxArrayEditorDialog
)
2289 EVT_BUTTON(28, wxPGArrayStringEditorDialog::OnCustomEditClick
)
2292 // -----------------------------------------------------------------------
2294 wxString
wxPGArrayStringEditorDialog::ArrayGet( size_t index
)
2296 return m_array
[index
];
2299 size_t wxPGArrayStringEditorDialog::ArrayGetCount()
2301 return m_array
.size();
2304 bool wxPGArrayStringEditorDialog::ArrayInsert( const wxString
& str
, int index
)
2309 m_array
.Insert(str
,index
);
2313 bool wxPGArrayStringEditorDialog::ArraySet( size_t index
, const wxString
& str
)
2315 m_array
[index
] = str
;
2319 void wxPGArrayStringEditorDialog::ArrayRemoveAt( int index
)
2321 m_array
.RemoveAt(index
);
2324 void wxPGArrayStringEditorDialog::ArraySwap( size_t first
, size_t second
)
2326 wxString old_str
= m_array
[first
];
2327 wxString new_str
= m_array
[second
];
2328 m_array
[first
] = new_str
;
2329 m_array
[second
] = old_str
;
2332 wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog()
2333 : wxArrayEditorDialog()
2338 void wxPGArrayStringEditorDialog::Init()
2340 m_pCallingClass
= (wxArrayStringProperty
*) NULL
;
2343 void wxPGArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent
& )
2345 wxASSERT( m_pCallingClass
);
2346 wxString str
= m_edValue
->GetValue();
2347 if ( m_pCallingClass
->OnCustomStringEdit(m_parent
,str
) )
2349 //m_edValue->SetValue ( str );
2350 m_lbStrings
->Append ( str
);
2351 m_array
.Add ( str
);
2356 // -----------------------------------------------------------------------
2357 // wxArrayStringProperty
2358 // -----------------------------------------------------------------------
2360 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty
, // Property name
2361 wxPGProperty
, // Property we inherit from
2362 wxArrayString
, // Value type name
2363 const wxArrayString
&, // Value type, as given in constructor
2364 TextCtrlAndButton
) // Initial editor
2366 wxArrayStringProperty::wxArrayStringProperty( const wxString
& label
,
2367 const wxString
& name
,
2368 const wxArrayString
& array
)
2369 : wxPGProperty(label
,name
)
2374 wxArrayStringProperty::~wxArrayStringProperty() { }
2376 void wxArrayStringProperty::OnSetValue()
2378 GenerateValueAsString();
2381 wxString
wxArrayStringProperty::GetValueAsString( int WXUNUSED(argFlags
) ) const
2386 // Converts wxArrayString to a string separated by delimeters and spaces.
2387 // preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash
2389 void wxPropertyGrid::ArrayStringToString( wxString
& dst
, const wxArrayString
& src
,
2390 wxChar preDelim
, wxChar postDelim
,
2396 unsigned int itemCount
= src
.size();
2404 else if ( (flags
& 1) )
2406 preas
[0] = preDelim
;
2413 dst
.append( preas
);
2415 wxASSERT( postDelim
);
2416 wxString
postDelimStr(postDelim
);
2417 //wxString preDelimStr(preDelim);
2419 for ( i
= 0; i
< itemCount
; i
++ )
2421 wxString
str( src
.Item(i
) );
2423 // Do some character conversion.
2424 // Convertes \ to \\ and <preDelim> to \<preDelim>
2425 // Useful when preDelim and postDelim are "\"".
2428 str
.Replace( wxS("\\"), wxS("\\\\"), true );
2430 str
.Replace( preas
, pdr
, true );
2435 if ( i
< (itemCount
-1) )
2437 dst
.append( postDelimStr
);
2438 dst
.append( wxS(" ") );
2439 dst
.append( preas
);
2441 else if ( preDelim
)
2442 dst
.append( postDelimStr
);
2446 #define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \
2447 wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxS('"'),wxS('"'),1);
2449 void wxArrayStringProperty::GenerateValueAsString()
2451 wxArrayString arr
= m_value
.GetArrayString();
2452 ARRSTRPROP_ARRAY_TO_STRING(m_display
, arr
)
2455 // Default implementation doesn't do anything.
2456 bool wxArrayStringProperty::OnCustomStringEdit( wxWindow
*, wxString
& )
2461 wxArrayEditorDialog
* wxArrayStringProperty::CreateEditorDialog()
2463 return new wxPGArrayStringEditorDialog();
2466 bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
,
2467 wxWindow
* WXUNUSED(primaryCtrl
),
2471 PrepareValueForDialogEditing(propGrid
);
2473 if ( !propGrid
->EditorValidate() )
2476 // Create editor dialog.
2477 wxArrayEditorDialog
* dlg
= CreateEditorDialog();
2478 #if wxUSE_VALIDATORS
2479 wxValidator
* validator
= GetValidator();
2480 wxPGInDialogValidator dialogValidator
;
2483 wxPGArrayStringEditorDialog
* strEdDlg
= wxDynamicCast(dlg
, wxPGArrayStringEditorDialog
);
2486 strEdDlg
->SetCustomButton(cbt
, this);
2488 dlg
->SetDialogValue( wxVariant(m_value
) );
2489 dlg
->Create(propGrid
, wxEmptyString
, m_label
);
2491 #if !wxPG_SMALL_SCREEN
2492 dlg
->Move( propGrid
->GetGoodEditorDialogPosition(this,dlg
->GetSize()) );
2501 int res
= dlg
->ShowModal();
2503 if ( res
== wxID_OK
&& dlg
->IsModified() )
2505 wxVariant value
= dlg
->GetDialogValue();
2506 if ( !value
.IsNull() )
2508 wxArrayString actualValue
= value
.GetArrayString();
2510 ARRSTRPROP_ARRAY_TO_STRING(tempStr
, actualValue
)
2511 #if wxUSE_VALIDATORS
2512 if ( dialogValidator
.DoValidate( propGrid
, validator
, tempStr
) )
2515 SetValueInEvent( actualValue
);
2532 bool wxArrayStringProperty::OnEvent( wxPropertyGrid
* propGrid
,
2536 if ( propGrid
->IsMainButtonEvent(event
) )
2537 return OnButtonClick(propGrid
,primary
,(const wxChar
*) NULL
);
2541 bool wxArrayStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
2545 WX_PG_TOKENIZER2_BEGIN(text
,wxS('"'))
2547 // Need to replace backslashes with empty characters
2548 // (opposite what is done in GenerateValueString).
2549 token
.Replace ( wxS("\\"), wxEmptyString
, true );
2553 WX_PG_TOKENIZER2_END()
2560 // -----------------------------------------------------------------------
2561 // wxPGInDialogValidator
2562 // -----------------------------------------------------------------------
2564 #if wxUSE_VALIDATORS
2565 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* propGrid
,
2566 wxValidator
* validator
,
2567 const wxString
& value
)
2572 wxTextCtrl
* tc
= m_textCtrl
;
2577 tc
= new wxTextCtrl( propGrid
, wxPG_SUBID_TEMP1
, wxEmptyString
,
2578 wxPoint(30000,30000));
2585 tc
->SetValue(value
);
2587 validator
->SetWindow(tc
);
2588 bool res
= validator
->Validate(propGrid
);
2593 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* WXUNUSED(propGrid
),
2594 wxValidator
* WXUNUSED(validator
),
2595 const wxString
& WXUNUSED(value
) )
2601 // -----------------------------------------------------------------------