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.
60 // -----------------------------------------------------------------------
62 // -----------------------------------------------------------------------
64 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty
,wxPGProperty
,
65 wxString
,const wxString
&,TextCtrl
)
67 wxStringProperty::wxStringProperty( const wxString
& label
,
69 const wxString
& value
)
70 : wxPGProperty(label
,name
)
75 void wxStringProperty::OnSetValue()
77 if ( !m_value
.IsNull() && m_value
.GetString() == wxS("<composed>") )
78 SetFlag(wxPG_PROP_COMPOSED_VALUE
);
80 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
83 GenerateComposedValue(s
, 0);
88 wxStringProperty::~wxStringProperty() { }
90 wxString
wxStringProperty::GetValueAsString( int argFlags
) const
92 wxString s
= m_value
.GetString();
94 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
96 // Value stored in m_value is non-editable, non-full value
97 if ( (argFlags
& wxPG_FULL_VALUE
) || (argFlags
& wxPG_EDITABLE_VALUE
) )
98 GenerateComposedValue(s
, argFlags
);
103 // If string is password and value is for visual purposes,
104 // then return asterisks instead the actual string.
105 if ( (m_flags
& wxPG_PROP_PASSWORD
) && !(argFlags
& (wxPG_FULL_VALUE
|wxPG_EDITABLE_VALUE
)) )
106 return wxString(wxChar('*'), s
.Length());
111 bool wxStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
113 if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
114 return wxPGProperty::StringToValue(variant
, text
, argFlags
);
116 if ( m_value
.GetString() != text
)
125 bool wxStringProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
127 if ( name
== wxPG_STRING_PASSWORD
)
129 m_flags
&= ~(wxPG_PROP_PASSWORD
);
130 if ( wxPGVariantToInt(value
) ) m_flags
|= wxPG_PROP_PASSWORD
;
137 // -----------------------------------------------------------------------
139 // -----------------------------------------------------------------------
141 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty
,wxPGProperty
,
144 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
,
145 long value
) : wxPGProperty(label
,name
)
150 wxIntProperty::wxIntProperty( const wxString
& label
, const wxString
& name
,
151 const wxLongLong
& value
) : wxPGProperty(label
,name
)
153 SetValue(wxLongLongToVariant(value
));
156 wxIntProperty::~wxIntProperty() { }
158 wxString
wxIntProperty::GetValueAsString( int ) const
160 if ( wxPGIsVariantType(m_value
, long) )
161 return wxString::Format(wxS("%li"),m_value
.GetLong());
163 wxLongLong
* ll
= &wxLongLongFromVariant(m_value
);
165 return ll
->ToString();
167 return wxEmptyString
;
170 bool wxIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
175 if ( text
.length() == 0 )
181 // We know it is a number, but let's still check
183 if ( text
.IsNumber() )
185 // Remove leading zeroes, so that the number is not interpreted as octal
186 wxString::const_iterator i
= text
.begin();
187 wxString::const_iterator iMax
= text
.end() - 1; // Let's allow one, last zero though
189 int firstNonZeroPos
= 0;
191 for ( ; i
!= iMax
; i
++ )
194 if ( c
!= wxS('0') && c
!= wxS(' ') )
199 wxString useText
= text
.substr(firstNonZeroPos
, text
.length() - firstNonZeroPos
);
201 bool isPrevLong
= wxPGIsVariantType(variant
, long);
203 wxLongLong_t value64
= 0;
205 if ( useText
.ToLongLong(&value64
, 10) &&
206 ( value64
>= INT_MAX
|| value64
<= INT_MIN
)
209 wxLongLong
* _m_value64
= &wxLongLongFromVariant(m_value
);
210 if ( isPrevLong
|| !_m_value64
|| _m_value64
->GetValue() != value64
)
212 variant
= wxLongLongToVariant(value64
);
217 if ( useText
.ToLong( &value32
, 0 ) )
219 if ( !isPrevLong
|| m_value
.GetLong() != value32
)
226 else if ( argFlags
& wxPG_REPORT_ERROR
)
232 bool wxIntProperty::IntToValue( wxVariant
& variant
, int value
, int WXUNUSED(argFlags
) ) const
234 if ( !wxPGIsVariantType(variant
, long) || variant
.GetLong() != value
)
236 variant
= (long)value
;
242 bool wxIntProperty::DoValidation( const wxPGProperty
* property
, wxLongLong_t
& value
, wxPGValidationInfo
* pValidationInfo
, int mode
)
245 wxLongLong_t min
= wxINT64_MIN
;
246 wxLongLong_t max
= wxINT64_MAX
;
251 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
);
252 if ( !variant
.IsNull() )
254 wxPGVariantToLongLong(variant
, &min
);
258 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
);
259 if ( !variant
.IsNull() )
261 wxPGVariantToLongLong(variant
, &max
);
269 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
270 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %lld or higher"),min
);
271 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
274 value
= max
- (min
- value
);
283 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
284 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %lld or higher"),min
);
285 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
288 value
= min
+ (value
- max
);
295 bool wxIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
298 if ( wxPGVariantToLongLong(value
, &ll
) )
299 return DoValidation(this, ll
, &validationInfo
, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
);
303 wxValidator
* wxIntProperty::GetClassValidator()
306 WX_PG_DOGETVALIDATOR_ENTRY()
308 // Atleast wxPython 2.6.2.1 required that the string argument is given
310 wxTextValidator
* validator
= new wxTextValidator(wxFILTER_NUMERIC
,&v
);
312 WX_PG_DOGETVALIDATOR_EXIT(validator
)
318 wxValidator
* wxIntProperty::DoGetValidator() const
320 return GetClassValidator();
323 // -----------------------------------------------------------------------
325 // -----------------------------------------------------------------------
328 #define wxPG_UINT_TEMPLATE_MAX 8
330 static const wxChar
* gs_uintTemplates32
[wxPG_UINT_TEMPLATE_MAX
] = {
331 wxT("%x"),wxT("0x%x"),wxT("$%x"),
332 wxT("%X"),wxT("0x%X"),wxT("$%X"),
336 static const wxChar
* gs_uintTemplates64
[wxPG_UINT_TEMPLATE_MAX
] = {
337 wxT("%") wxLongLongFmtSpec
wxT("x"),
338 wxT("0x%") wxLongLongFmtSpec
wxT("x"),
339 wxT("$%") wxLongLongFmtSpec
wxT("x"),
340 wxT("%") wxLongLongFmtSpec
wxT("X"),
341 wxT("0x%") wxLongLongFmtSpec
wxT("X"),
342 wxT("$%") wxLongLongFmtSpec
wxT("X"),
343 wxT("%") wxLongLongFmtSpec
wxT("u"),
344 wxT("%") wxLongLongFmtSpec
wxT("o")
347 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty
,wxPGProperty
,
348 long,unsigned long,TextCtrl
)
350 void wxUIntProperty::Init()
352 m_base
= 6; // This is magic number for dec base (must be same as in setattribute)
354 m_prefix
= wxPG_PREFIX_NONE
;
357 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
,
358 unsigned long value
) : wxPGProperty(label
,name
)
361 SetValue((long)value
);
364 wxUIntProperty::wxUIntProperty( const wxString
& label
, const wxString
& name
,
365 const wxULongLong
& value
) : wxPGProperty(label
,name
)
368 SetValue(wxULongLongToVariant(value
));
371 wxUIntProperty::~wxUIntProperty() { }
373 wxString
wxUIntProperty::GetValueAsString( int ) const
375 size_t index
= m_base
+ m_prefix
;
376 if ( index
>= wxPG_UINT_TEMPLATE_MAX
)
377 index
= wxPG_BASE_DEC
;
379 if ( wxPGIsVariantType(m_value
, long) )
380 return wxString::Format(gs_uintTemplates32
[index
],(unsigned long)m_value
.GetLong());
382 return wxString::Format(gs_uintTemplates64
[index
],wxULongLongFromVariant(m_value
).GetValue());
385 bool wxUIntProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const
387 //long unsigned value32 = 0;
388 bool isPrevLong
= wxPGIsVariantType(variant
, long);
390 if ( text
.length() == 0 )
397 if ( text
[0] == wxS('$') )
400 wxULongLong_t value64
= 0;
401 wxString s
= text
.substr(start
, text
.length() - start
);
403 if ( s
.ToULongLong(&value64
, (unsigned int)m_realBase
) )
405 if ( value64
>= LONG_MAX
)
407 wxULongLong
* _m_value64
= &wxULongLongFromVariant(m_value
);
408 if ( isPrevLong
|| !_m_value64
|| _m_value64
->GetValue() != value64
)
410 variant
= wxULongLongToVariant(value64
);
416 unsigned long value32
= wxLongLong(value64
).GetLo();
417 if ( !isPrevLong
|| m_value
.GetLong() != (long)value32
)
419 variant
= (long)value32
;
428 bool wxUIntProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
430 if ( m_value
!= (long)number
)
432 variant
= (long)number
;
439 #define wxUINT64_MAX ULLONG_MAX
440 #define wxUINT64_MIN wxULL(0)
442 #define wxUINT64_MAX wxULL(0xFFFFFFFFFFFFFFFF)
443 #define wxUINT64_MIN wxULL(0)
446 bool wxUIntProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
450 if ( wxPGVariantToULongLong(value
, &ll
) )
452 wxULongLong_t min
= wxUINT64_MIN
;
453 wxULongLong_t max
= wxUINT64_MAX
;
456 variant
= GetAttribute(wxPGGlobalVars
->m_strMin
);
457 if ( !variant
.IsNull() )
459 wxPGVariantToULongLong(variant
, &min
);
462 validationInfo
.m_failureMessage
= wxString::Format(_("Value must be %llu or higher"),min
);
466 variant
= GetAttribute(wxPGGlobalVars
->m_strMax
);
467 if ( !variant
.IsNull() )
469 wxPGVariantToULongLong(variant
, &max
);
472 validationInfo
.m_failureMessage
= wxString::Format(_("Value must be %llu or less"),max
);
480 bool wxUIntProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
482 if ( name
== wxPG_UINT_BASE
)
484 int val
= value
.GetLong();
486 m_realBase
= (wxByte
) val
;
487 if ( m_realBase
> 16 )
491 // Translate logical base to a template array index
493 if ( val
== wxPG_BASE_HEX
)
495 else if ( val
== wxPG_BASE_DEC
)
497 else if ( val
== wxPG_BASE_HEXL
)
501 else if ( name
== wxPG_UINT_PREFIX
)
503 m_prefix
= (wxByte
) value
.GetLong();
509 // -----------------------------------------------------------------------
511 // -----------------------------------------------------------------------
513 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty
,wxPGProperty
,
514 double,double,TextCtrl
)
516 wxFloatProperty::wxFloatProperty( const wxString
& label
,
517 const wxString
& name
,
519 : wxPGProperty(label
,name
)
525 wxFloatProperty::~wxFloatProperty() { }
527 // This helper method provides standard way for floating point-using
528 // properties to convert values to string.
529 void wxPropertyGrid::DoubleToString(wxString
& target
,
533 wxString
* precTemplate
)
535 if ( precision
>= 0 )
539 precTemplate
= &text1
;
541 if ( !precTemplate
->length() )
543 *precTemplate
= wxS("%.");
544 *precTemplate
<< wxString::Format( wxS("%i"), precision
);
545 *precTemplate
<< wxS('f');
548 target
.Printf( precTemplate
->c_str(), value
);
552 target
.Printf( wxS("%f"), value
);
555 if ( removeZeroes
&& precision
!= 0 && target
.length() )
557 // Remove excess zeroes (do not remove this code just yet,
558 // since sprintf can't do the same consistently across platforms).
559 wxString::const_iterator i
= target
.end() - 1;
560 size_t new_len
= target
.length() - 1;
562 for ( ; i
!= target
.begin(); i
-- )
564 if ( *i
!= wxS('0') )
569 wxChar cur_char
= *i
;
570 if ( cur_char
!= wxS('.') && cur_char
!= wxS(',') )
573 if ( new_len
!= target
.length() )
574 target
.resize(new_len
);
578 wxString
wxFloatProperty::GetValueAsString( int argFlags
) const
581 if ( !m_value
.IsNull() )
583 wxPropertyGrid::DoubleToString(text
,
586 !(argFlags
& wxPG_FULL_VALUE
),
592 bool wxFloatProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
597 if ( text
.length() == 0 )
603 bool res
= text
.ToDouble(&value
);
606 if ( m_value
!= value
)
612 else if ( argFlags
& wxPG_REPORT_ERROR
)
618 bool wxFloatProperty::DoValidation( const wxPGProperty
* property
, double& value
, wxPGValidationInfo
* pValidationInfo
, int mode
)
621 double min
= (double)wxINT64_MIN
;
622 double max
= (double)wxINT64_MAX
;
627 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMin
);
628 if ( !variant
.IsNull() )
630 wxPGVariantToDouble(variant
, &min
);
634 variant
= property
->GetAttribute(wxPGGlobalVars
->m_strMax
);
635 if ( !variant
.IsNull() )
637 wxPGVariantToDouble(variant
, &max
);
645 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
646 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %f or higher"),min
);
647 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
650 value
= max
- (min
- value
);
657 wxPGVariantToDouble(variant
, &max
);
660 if ( mode
== wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
)
661 pValidationInfo
->m_failureMessage
= wxString::Format(_("Value must be %f or less"),max
);
662 else if ( mode
== wxPG_PROPERTY_VALIDATION_SATURATE
)
665 value
= min
+ (value
- max
);
672 bool wxFloatProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& validationInfo
) const
675 if ( wxPGVariantToDouble(value
, &fpv
) )
676 return DoValidation(this, fpv
, &validationInfo
, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE
);
680 bool wxFloatProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
682 if ( name
== wxPG_FLOAT_PRECISION
)
684 m_precision
= value
.GetLong();
690 wxValidator
* wxFloatProperty::DoGetValidator() const
692 return wxIntProperty::GetClassValidator();
695 // -----------------------------------------------------------------------
697 // -----------------------------------------------------------------------
699 // We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since
700 // there is a custom GetEditorClass.
702 IMPLEMENT_DYNAMIC_CLASS(wxBoolProperty
, wxPGProperty
)
704 const wxPGEditor
* wxBoolProperty::DoGetEditorClass() const
706 // Select correct editor control.
707 #if wxPG_INCLUDE_CHECKBOX
708 if ( !(m_flags
& wxPG_PROP_USE_CHECKBOX
) )
709 return wxPG_EDITOR(Choice
);
710 return wxPG_EDITOR(CheckBox
);
712 return wxPG_EDITOR(Choice
);
716 wxBoolProperty::wxBoolProperty( const wxString
& label
, const wxString
& name
, bool value
) :
717 wxPGProperty(label
,name
)
719 SetValue(wxPGVariant_Bool(value
));
721 m_flags
|= wxPG_PROP_USE_DCC
;
724 wxBoolProperty::~wxBoolProperty() { }
726 wxString
wxBoolProperty::GetValueAsString( int argFlags
) const
728 bool value
= m_value
.GetBool();
730 // As a fragment of composite string value,
731 // make it a little more readable.
732 if ( argFlags
& wxPG_COMPOSITE_FRAGMENT
)
740 if ( argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
)
741 return wxEmptyString
;
744 if ( wxPGGlobalVars
->m_autoGetTranslation
)
745 notFmt
= _("Not %s");
747 notFmt
= wxS("Not %s");
749 return wxString::Format(notFmt
.c_str(), m_label
.c_str());
753 if ( !(argFlags
& wxPG_FULL_VALUE
) )
755 return wxPGGlobalVars
->m_boolChoices
[value
?1:0].GetText();
760 if (value
) text
= wxS("true");
761 else text
= wxS("false");
766 int wxBoolProperty::GetChoiceInfo( wxPGChoiceInfo
* choiceinfo
)
768 if ( IsValueUnspecified() )
772 choiceinfo
->m_choices
= &wxPGGlobalVars
->m_boolChoices
;
773 return m_value
.GetBool()?1:0;
776 bool wxBoolProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int WXUNUSED(argFlags
) ) const
779 if ( text
.CmpNoCase(wxPGGlobalVars
->m_boolChoices
[1].GetText()) == 0 ||
780 text
.CmpNoCase(wxS("true")) == 0 ||
781 text
.CmpNoCase(m_label
) == 0 )
784 if ( text
.length() == 0 )
790 bool oldValue
= m_value
.GetBool();
792 if ( (oldValue
&& !value
) || (!oldValue
&& value
) )
794 variant
= wxPGVariant_Bool(value
);
800 bool wxBoolProperty::IntToValue( wxVariant
& variant
, int value
, int ) const
802 bool boolValue
= value
? true : false;
803 bool oldValue
= m_value
.GetBool();
805 if ( oldValue
!= boolValue
)
807 variant
= wxPGVariant_Bool(boolValue
);
813 bool wxBoolProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
815 #if wxPG_INCLUDE_CHECKBOX
816 if ( name
== wxPG_BOOL_USE_CHECKBOX
)
818 int ival
= wxPGVariantToInt(value
);
820 m_flags
|= wxPG_PROP_USE_CHECKBOX
;
822 m_flags
&= ~(wxPG_PROP_USE_CHECKBOX
);
826 if ( name
== wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING
)
828 int ival
= wxPGVariantToInt(value
);
830 m_flags
|= wxPG_PROP_USE_DCC
;
832 m_flags
&= ~(wxPG_PROP_USE_DCC
);
838 // -----------------------------------------------------------------------
839 // wxBaseEnumProperty
840 // -----------------------------------------------------------------------
842 int wxBaseEnumProperty::ms_nextIndex
= -2;
844 wxBaseEnumProperty::wxBaseEnumProperty( const wxString
& label
, const wxString
& name
)
845 : wxPGProperty(label
,name
)
847 m_value
= wxPGVariant_Zero
;
850 /** If has values array, then returns number at index with value -
851 otherwise just returns the value.
853 int wxBaseEnumProperty::GetIndexForValue( int value
) const
858 void wxBaseEnumProperty::OnSetValue()
860 if ( wxPGIsVariantType(m_value
, long) )
861 ValueFromInt_( m_value
, m_value
.GetLong(), wxPG_FULL_VALUE
);
862 else if ( wxPGIsVariantType(m_value
, string
) )
863 ValueFromString_( m_value
, m_value
.GetString(), 0 );
867 if ( ms_nextIndex
!= -2 )
869 m_index
= ms_nextIndex
;
874 bool wxBaseEnumProperty::ValidateValue( wxVariant
& value
, wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
876 // Make sure string value is in the list,
877 // unless property has string as preferred value type
878 // To reduce code size, use conversion here as well
879 if ( wxPGIsVariantType(value
, string
) &&
880 !this->IsKindOf(CLASSINFO(wxEditEnumProperty
)) )
881 return ValueFromString_( value
, value
.GetString(), wxPG_PROPERTY_SPECIFIC
);
886 wxString
wxBaseEnumProperty::GetValueAsString( int ) const
888 if ( wxPGIsVariantType(m_value
, string
) )
889 return m_value
.GetString();
894 const wxString
* pstr
= GetEntry( m_index
, &unusedVal
);
899 return wxEmptyString
;
902 bool wxBaseEnumProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
904 return ValueFromString_( variant
, text
, argFlags
);
907 bool wxBaseEnumProperty::IntToValue( wxVariant
& variant
, int intVal
, int argFlags
) const
909 return ValueFromInt_( variant
, intVal
, argFlags
);
912 bool wxBaseEnumProperty::ValueFromString_( wxVariant
& value
, const wxString
& text
, int argFlags
) const
915 const wxString
* entryLabel
;
920 entryLabel
= GetEntry(i
, &entryValue
);
923 if ( text
.CmpNoCase(*entryLabel
) == 0 )
926 useValue
= (long)entryValue
;
931 entryLabel
= GetEntry(i
, &entryValue
);
936 bool isEdit
= this->IsKindOf(CLASSINFO(wxEditEnumProperty
));
938 // If text not any of the choices, store as text instead
939 // (but only if we are wxEditEnumProperty)
940 if ( useIndex
== -1 &&
941 (!wxPGIsVariantType(m_value
, string
) || (m_value
.GetString() != text
)) &&
947 int setAsNextIndex
= -2;
954 else if ( m_index
!= useIndex
)
956 if ( useIndex
!= -1 )
958 setAsNextIndex
= useIndex
;
959 value
= (long)useValue
;
964 value
= wxPGVariant_MinusOne
;
968 if ( setAsNextIndex
!= -2 )
970 // If wxPG_PROPERTY_SPECIFIC is set, then this is done for
971 // validation purposes only, and index must not be changed
972 if ( !(argFlags
& wxPG_PROPERTY_SPECIFIC
) )
973 ms_nextIndex
= setAsNextIndex
;
975 if ( isEdit
|| setAsNextIndex
!= -1 )
983 bool wxBaseEnumProperty::ValueFromInt_( wxVariant
& variant
, int intVal
, int argFlags
) const
985 // If wxPG_FULL_VALUE is *not* in argFlags, then intVal is index from combo box.
989 if ( argFlags
& wxPG_FULL_VALUE
)
991 ms_nextIndex
= GetIndexForValue( intVal
);
995 if ( m_index
!= intVal
)
997 ms_nextIndex
= intVal
;
1001 if ( ms_nextIndex
!= -2 )
1003 if ( !(argFlags
& wxPG_FULL_VALUE
) )
1004 GetEntry(intVal
, &intVal
);
1006 variant
= (long)intVal
;
1014 void wxBaseEnumProperty::SetIndex( int index
)
1020 int wxBaseEnumProperty::GetIndex() const
1022 if ( ms_nextIndex
!= -2 )
1023 return ms_nextIndex
;
1027 // -----------------------------------------------------------------------
1029 // -----------------------------------------------------------------------
1031 IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty
, wxPGProperty
)
1033 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty
,long,Choice
)
1035 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1036 const long* values
, int value
) : wxBaseEnumProperty(label
,name
)
1042 m_choices
.Add(labels
,values
);
1044 if ( GetItemCount() )
1045 SetValue( (long)value
);
1049 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1050 const long* values
, wxPGChoices
* choicesCache
, int value
)
1051 : wxBaseEnumProperty(label
,name
)
1055 wxASSERT( choicesCache
);
1057 if ( choicesCache
->IsOk() )
1059 m_choices
.Assign( *choicesCache
);
1060 m_value
= wxPGVariant_Zero
;
1064 m_choices
.Add(labels
,values
);
1066 if ( GetItemCount() )
1067 SetValue( (long)value
);
1071 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
,
1072 const wxArrayString
& labels
, const wxArrayInt
& values
, int value
) : wxBaseEnumProperty(label
,name
)
1076 if ( &labels
&& labels
.size() )
1078 m_choices
.Set(labels
, values
);
1080 if ( GetItemCount() )
1081 SetValue( (long)value
);
1085 wxEnumProperty::wxEnumProperty( const wxString
& label
, const wxString
& name
,
1086 wxPGChoices
& choices
, int value
)
1087 : wxBaseEnumProperty(label
,name
)
1089 m_choices
.Assign( choices
);
1091 if ( GetItemCount() )
1092 SetValue( (long)value
);
1095 int wxEnumProperty::GetIndexForValue( int value
) const
1097 if ( !m_choices
.IsOk() )
1100 if ( m_choices
.HasValues() )
1102 int intVal
= m_choices
.Index(value
);
1110 wxEnumProperty::~wxEnumProperty ()
1114 const wxString
* wxEnumProperty::GetEntry( size_t index
, int* pvalue
) const
1116 if ( m_choices
.IsOk() && index
< m_choices
.GetCount() )
1118 int value
= (int)index
;
1119 if ( m_choices
.HasValue(index
) )
1120 value
= m_choices
.GetValue(index
);
1125 return &m_choices
.GetLabel(index
);
1127 return (const wxString
*) NULL
;
1130 int wxEnumProperty::GetChoiceInfo( wxPGChoiceInfo
* choiceinfo
)
1133 choiceinfo
->m_choices
= &m_choices
;
1135 if ( !m_choices
.IsOk() )
1141 // -----------------------------------------------------------------------
1142 // wxEditEnumProperty
1143 // -----------------------------------------------------------------------
1145 IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty
, wxPGProperty
)
1147 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty
,wxString
,ComboBox
)
1149 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1150 const long* values
, const wxString
& value
)
1151 : wxEnumProperty(label
,name
,labels
,values
,0)
1156 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
, const wxChar
** labels
,
1157 const long* values
, wxPGChoices
* choicesCache
, const wxString
& value
)
1158 : wxEnumProperty(label
,name
,labels
,values
,choicesCache
,0)
1163 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
,
1164 const wxArrayString
& labels
, const wxArrayInt
& values
, const wxString
& value
)
1165 : wxEnumProperty(label
,name
,labels
,values
,0)
1170 wxEditEnumProperty::wxEditEnumProperty( const wxString
& label
, const wxString
& name
,
1171 wxPGChoices
& choices
, const wxString
& value
)
1172 : wxEnumProperty(label
,name
,choices
,0)
1177 wxEditEnumProperty::~wxEditEnumProperty()
1181 // -----------------------------------------------------------------------
1183 // -----------------------------------------------------------------------
1185 IMPLEMENT_DYNAMIC_CLASS(wxFlagsProperty
,wxPGProperty
)
1187 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty
,long,TextCtrl
)
1189 void wxFlagsProperty::Init()
1191 SetFlag(wxPG_PROP_AGGREGATE
); // This is must be done here to support flag props
1192 // with inital zero children.
1194 long value
= m_value
;
1197 // Generate children
1201 unsigned int prevChildCount
= m_children
.GetCount();
1204 if ( prevChildCount
)
1206 wxPropertyGridPageState
* state
= GetParentState();
1208 // State safety check (it may be NULL in immediate parent)
1213 wxPGProperty
* selected
= state
->GetSelection();
1216 if ( selected
->GetParent() == this )
1217 oldSel
= selected
->GetArrIndex();
1218 else if ( selected
== this )
1222 state
->DoClearSelection();
1225 // Delete old children
1226 for ( i
=0; i
<prevChildCount
; i
++ )
1227 delete ( (wxPGProperty
*) m_children
[i
] );
1231 if ( m_choices
.IsOk() )
1233 const wxPGChoices
& choices
= m_choices
;
1235 for ( i
=0; i
<GetItemCount(); i
++ )
1238 if ( choices
.HasValue(i
) )
1239 child_val
= ( value
& choices
.GetValue(i
) )?true:false;
1241 child_val
= ( value
& (1<<i
) )?true:false;
1243 wxPGProperty
* boolProp
;
1244 wxString label
= GetLabel(i
);
1247 if ( wxPGGlobalVars
->m_autoGetTranslation
)
1249 boolProp
= new wxBoolProperty( ::wxGetTranslation(label
), label
, child_val
);
1254 boolProp
= new wxBoolProperty( label
, label
, child_val
);
1259 m_oldChoicesData
= m_choices
.GetDataPtr();
1262 m_oldValue
= m_value
;
1264 if ( prevChildCount
)
1265 SubPropsChanged(oldSel
);
1268 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1269 const wxChar
** labels
, const long* values
, long value
) : wxPGProperty(label
,name
)
1271 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1275 m_choices
.Set(labels
,values
);
1277 wxASSERT( GetItemCount() );
1283 m_value
= wxPGVariant_Zero
;
1287 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1288 const wxArrayString
& labels
, const wxArrayInt
& values
, int value
)
1289 : wxPGProperty(label
,name
)
1291 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1293 if ( &labels
&& labels
.size() )
1295 m_choices
.Set(labels
,values
);
1297 wxASSERT( GetItemCount() );
1299 SetValue( (long)value
);
1303 m_value
= wxPGVariant_Zero
;
1307 wxFlagsProperty::wxFlagsProperty( const wxString
& label
, const wxString
& name
,
1308 wxPGChoices
& choices
, long value
)
1309 : wxPGProperty(label
,name
)
1311 m_oldChoicesData
= (wxPGChoicesData
*) NULL
;
1313 if ( choices
.IsOk() )
1315 m_choices
.Assign(choices
);
1317 wxASSERT( GetItemCount() );
1323 m_value
= wxPGVariant_Zero
;
1327 wxFlagsProperty::~wxFlagsProperty()
1331 void wxFlagsProperty::OnSetValue()
1333 if ( !m_choices
.IsOk() || !GetItemCount() )
1335 m_value
= wxPGVariant_Zero
;
1339 long val
= m_value
.GetLong();
1343 // normalize the value (i.e. remove extra flags)
1345 const wxPGChoices
& choices
= m_choices
;
1346 for ( i
= 0; i
< GetItemCount(); i
++ )
1348 if ( choices
.HasValue(i
) )
1349 fullFlags
|= choices
.GetValue(i
);
1351 fullFlags
|= (1<<i
);
1358 // Need to (re)init now?
1359 if ( GetChildCount() != GetItemCount() ||
1360 m_choices
.GetDataPtr() != m_oldChoicesData
)
1366 long newFlags
= m_value
;
1368 if ( newFlags
!= m_oldValue
)
1370 // Set child modified states
1372 const wxPGChoices
& choices
= m_choices
;
1373 for ( i
= 0; i
<GetItemCount(); i
++ )
1377 if ( choices
.HasValue(i
) )
1378 flag
= choices
.GetValue(i
);
1382 if ( (newFlags
& flag
) != (m_oldValue
& flag
) )
1383 Item(i
)->SetFlag( wxPG_PROP_MODIFIED
);
1386 m_oldValue
= newFlags
;
1390 wxString
wxFlagsProperty::GetValueAsString( int ) const
1394 if ( !m_choices
.IsOk() )
1397 long flags
= m_value
;
1399 const wxPGChoices
& choices
= m_choices
;
1401 for ( i
= 0; i
< GetItemCount(); i
++ )
1404 if ( choices
.HasValue(i
) )
1405 doAdd
= ( flags
& choices
.GetValue(i
) );
1407 doAdd
= ( flags
& (1<<i
) );
1411 text
+= choices
.GetLabel(i
);
1416 // remove last comma
1417 if ( text
.Len() > 1 )
1418 text
.Truncate ( text
.Len() - 2 );
1423 // Translate string into flag tokens
1424 bool wxFlagsProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
1426 if ( !m_choices
.IsOk() )
1430 long oldValue
= m_value
;
1432 // semicolons are no longer valid delimeters
1433 WX_PG_TOKENIZER1_BEGIN(text
,wxS(','))
1435 if ( token
.length() )
1437 // Determine which one it is
1438 long bit
= IdToBit( token
);
1451 WX_PG_TOKENIZER1_END()
1455 if ( newFlags
!= oldValue
)
1461 // Converts string id to a relevant bit.
1462 long wxFlagsProperty::IdToBit( const wxString
& id
) const
1465 for ( i
= 0; i
< GetItemCount(); i
++ )
1467 if ( id
== GetLabel(i
) )
1469 if ( m_choices
.HasValue(i
) )
1470 return m_choices
.GetValue(i
);
1477 void wxFlagsProperty::RefreshChildren()
1479 if ( !m_choices
.IsOk() || !GetChildCount() ) return;
1481 int flags
= m_value
.GetLong();
1483 const wxPGChoices
& choices
= m_choices
;
1485 for ( i
= 0; i
< GetItemCount(); i
++ )
1489 if ( choices
.HasValue(i
) )
1490 flag
= choices
.GetValue(i
);
1494 long subVal
= flags
& flag
;
1495 wxPGProperty
* p
= Item(i
);
1497 if ( subVal
!= (m_oldValue
& flag
) )
1498 p
->SetFlag( wxPG_PROP_MODIFIED
);
1500 p
->SetValue( subVal
?true:false );
1506 void wxFlagsProperty::ChildChanged( wxVariant
& thisValue
, int childIndex
, wxVariant
& childValue
) const
1508 long oldValue
= thisValue
.GetLong();
1509 long val
= childValue
.GetLong();
1510 unsigned long vi
= (1<<childIndex
);
1511 if ( m_choices
.HasValue(childIndex
) ) vi
= m_choices
.GetValue(childIndex
);
1513 thisValue
= (long)(oldValue
| vi
);
1515 thisValue
= (long)(oldValue
& ~(vi
));
1518 int wxFlagsProperty::GetChoiceInfo( wxPGChoiceInfo
* choiceinfo
)
1521 choiceinfo
->m_choices
= &m_choices
;
1525 // -----------------------------------------------------------------------
1527 // -----------------------------------------------------------------------
1529 WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxDirProperty
,wxLongStringProperty
,const wxString
&)
1531 wxDirProperty::wxDirProperty( const wxString
& name
, const wxString
& label
, const wxString
& value
)
1532 : wxLongStringProperty(name
,label
,value
)
1534 m_flags
|= wxPG_NO_ESCAPE
;
1536 wxDirProperty::~wxDirProperty() { }
1538 wxValidator
* wxDirProperty::DoGetValidator() const
1540 return wxFileProperty::GetClassValidator();
1543 bool wxDirProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value
)
1545 wxSize
dlg_sz(300,400);
1547 wxDirDialog
dlg( propGrid
,
1548 m_dlgMessage
.length() ? m_dlgMessage
: wxString(_("Choose a directory:")),
1551 #if !wxPG_SMALL_SCREEN
1552 propGrid
->GetGoodEditorDialogPosition(this,dlg_sz
),
1559 if ( dlg
.ShowModal() == wxID_OK
)
1561 value
= dlg
.GetPath();
1567 bool wxDirProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1569 if ( name
== wxPG_DIR_DIALOG_MESSAGE
)
1571 m_dlgMessage
= value
.GetString();
1577 // -----------------------------------------------------------------------
1578 // wxPGFileDialogAdapter
1579 // -----------------------------------------------------------------------
1581 bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property
)
1583 wxFileProperty
* fileProp
= NULL
;
1587 if ( property
->IsKindOf(CLASSINFO(wxFileProperty
)) )
1589 fileProp
= ((wxFileProperty
*)property
);
1590 path
= fileProp
->m_filename
.GetPath();
1591 indFilter
= fileProp
->m_indFilter
;
1593 if ( !path
.length() && fileProp
->m_basePath
.length() )
1594 path
= fileProp
->m_basePath
;
1598 wxFileName
fn(property
->GetValue().GetString());
1599 path
= fn
.GetPath();
1602 wxFileDialog
dlg( propGrid
->GetPanel(),
1603 property
->GetAttribute(wxS("DialogTitle"), _("Choose a file")),
1604 property
->GetAttribute(wxS("InitialPath"), path
),
1606 property
->GetAttribute(wxPG_FILE_WILDCARD
, _("All files (*.*)|*.*")),
1608 wxDefaultPosition
);
1610 if ( indFilter
>= 0 )
1611 dlg
.SetFilterIndex( indFilter
);
1613 if ( dlg
.ShowModal() == wxID_OK
)
1616 fileProp
->m_indFilter
= dlg
.GetFilterIndex();
1617 SetValue( dlg
.GetPath() );
1623 // -----------------------------------------------------------------------
1625 // -----------------------------------------------------------------------
1627 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty
,wxPGProperty
,
1628 wxString
,const wxString
&,TextCtrlAndButton
)
1630 wxFileProperty::wxFileProperty( const wxString
& label
, const wxString
& name
,
1631 const wxString
& value
) : wxPGProperty(label
,name
)
1633 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1635 SetAttribute( wxPG_FILE_WILDCARD
, _("All files (*.*)|*.*") );
1640 wxFileProperty::~wxFileProperty() {}
1642 #if wxUSE_VALIDATORS
1644 wxValidator
* wxFileProperty::GetClassValidator()
1646 WX_PG_DOGETVALIDATOR_ENTRY()
1648 // Atleast wxPython 2.6.2.1 required that the string argument is given
1650 wxTextValidator
* validator
= new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST
,&v
);
1652 wxArrayString exChars
;
1653 exChars
.Add(wxS("?"));
1654 exChars
.Add(wxS("*"));
1655 exChars
.Add(wxS("|"));
1656 exChars
.Add(wxS("<"));
1657 exChars
.Add(wxS(">"));
1658 exChars
.Add(wxS("\""));
1660 validator
->SetExcludes(exChars
);
1662 WX_PG_DOGETVALIDATOR_EXIT(validator
)
1665 wxValidator
* wxFileProperty::DoGetValidator() const
1667 return GetClassValidator();
1672 void wxFileProperty::OnSetValue()
1674 const wxString
& fnstr
= m_value
.GetString();
1678 if ( !m_filename
.HasName() )
1680 m_value
= wxPGVariant_EmptyString
;
1684 // Find index for extension.
1685 if ( m_indFilter
< 0 && fnstr
.length() )
1687 wxString ext
= m_filename
.GetExt();
1690 size_t len
= m_wildcard
.length();
1692 pos
= m_wildcard
.find(wxS("|"), pos
);
1693 while ( pos
!= wxString::npos
&& pos
< (len
-3) )
1695 size_t ext_begin
= pos
+ 3;
1697 pos
= m_wildcard
.find(wxS("|"), ext_begin
);
1698 if ( pos
== wxString::npos
)
1700 wxString found_ext
= m_wildcard
.substr(ext_begin
, pos
-ext_begin
);
1702 if ( found_ext
.length() > 0 )
1704 if ( found_ext
[0] == wxS('*') )
1706 m_indFilter
= curind
;
1709 if ( ext
.CmpNoCase(found_ext
) == 0 )
1711 m_indFilter
= curind
;
1717 pos
= m_wildcard
.find(wxS("|"), pos
+1);
1724 wxString
wxFileProperty::GetValueAsString( int argFlags
) const
1726 // Always return empty string when name component is empty
1727 wxString fullName
= m_filename
.GetFullName();
1728 if ( !fullName
.length() )
1731 if ( argFlags
& wxPG_FULL_VALUE
)
1733 return m_filename
.GetFullPath();
1735 else if ( m_flags
& wxPG_PROP_SHOW_FULL_FILENAME
)
1737 if ( m_basePath
.Length() )
1739 wxFileName
fn2(m_filename
);
1740 fn2
.MakeRelativeTo(m_basePath
);
1741 return fn2
.GetFullPath();
1743 return m_filename
.GetFullPath();
1746 return m_filename
.GetFullName();
1749 wxPGEditorDialogAdapter
* wxFileProperty::GetEditorDialog() const
1751 return new wxPGFileDialogAdapter();
1754 bool wxFileProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
1756 if ( (m_flags
& wxPG_PROP_SHOW_FULL_FILENAME
) || (argFlags
& wxPG_FULL_VALUE
) )
1758 if ( m_filename
!= text
)
1766 if ( m_filename
.GetFullName() != text
)
1768 wxFileName fn
= m_filename
;
1769 fn
.SetFullName(text
);
1770 variant
= fn
.GetFullPath();
1778 bool wxFileProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1780 // Return false on some occasions to make sure those attribs will get
1781 // stored in m_attributes.
1782 if ( name
== wxPG_FILE_SHOW_FULL_PATH
)
1784 if ( wxPGVariantToInt(value
) )
1785 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1787 m_flags
&= ~(wxPG_PROP_SHOW_FULL_FILENAME
);
1790 else if ( name
== wxPG_FILE_WILDCARD
)
1792 m_wildcard
= value
.GetString();
1794 else if ( name
== wxPG_FILE_SHOW_RELATIVE_PATH
)
1796 m_basePath
= value
.GetString();
1798 // Make sure wxPG_FILE_SHOW_FULL_PATH is also set
1799 m_flags
|= wxPG_PROP_SHOW_FULL_FILENAME
;
1801 else if ( name
== wxPG_FILE_INITIAL_PATH
)
1803 m_initialPath
= value
.GetString();
1806 else if ( name
== wxPG_FILE_DIALOG_TITLE
)
1808 m_dlgTitle
= value
.GetString();
1814 // -----------------------------------------------------------------------
1815 // wxPGLongStringDialogAdapter
1816 // -----------------------------------------------------------------------
1818 bool wxPGLongStringDialogAdapter::DoShowDialog( wxPropertyGrid
* propGrid
, wxPGProperty
* property
)
1820 wxString val1
= property
->GetValueAsString(0);
1821 wxString val_orig
= val1
;
1824 if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) )
1825 wxPropertyGrid::ExpandEscapeSequences(value
, val1
);
1827 value
= wxString(val1
);
1829 // Run editor dialog.
1830 if ( wxLongStringProperty::DisplayEditorDialog(property
, propGrid
, value
) )
1832 if ( !property
->HasFlag(wxPG_PROP_NO_ESCAPE
) )
1833 wxPropertyGrid::CreateEscapeSequences(val1
,value
);
1837 if ( val1
!= val_orig
)
1846 // -----------------------------------------------------------------------
1847 // wxLongStringProperty
1848 // -----------------------------------------------------------------------
1850 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty
,wxPGProperty
,
1851 wxString
,const wxString
&,TextCtrlAndButton
)
1853 wxLongStringProperty::wxLongStringProperty( const wxString
& label
, const wxString
& name
,
1854 const wxString
& value
) : wxPGProperty(label
,name
)
1859 wxLongStringProperty::~wxLongStringProperty() {}
1861 wxString
wxLongStringProperty::GetValueAsString( int ) const
1866 bool wxLongStringProperty::OnEvent( wxPropertyGrid
* propGrid
, wxWindow
* WXUNUSED(primary
),
1869 if ( propGrid
->IsMainButtonEvent(event
) )
1872 PrepareValueForDialogEditing(propGrid
);
1874 wxString val1
= GetValueAsString(0);
1875 wxString val_orig
= val1
;
1878 if ( !(m_flags
& wxPG_PROP_NO_ESCAPE
) )
1879 wxPropertyGrid::ExpandEscapeSequences(value
,val1
);
1881 value
= wxString(val1
);
1883 // Run editor dialog.
1884 if ( OnButtonClick(propGrid
,value
) )
1886 if ( !(m_flags
& wxPG_PROP_NO_ESCAPE
) )
1887 wxPropertyGrid::CreateEscapeSequences(val1
,value
);
1891 if ( val1
!= val_orig
)
1893 SetValueInEvent( val1
);
1901 bool wxLongStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
, wxString
& value
)
1903 return DisplayEditorDialog(this, propGrid
, value
);
1906 bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty
* prop
, wxPropertyGrid
* propGrid
, wxString
& value
)
1909 // launch editor dialog
1910 wxDialog
* dlg
= new wxDialog(propGrid
,-1,prop
->GetLabel(),wxDefaultPosition
,wxDefaultSize
,
1911 wxDEFAULT_DIALOG_STYLE
|wxRESIZE_BORDER
|wxCLIP_CHILDREN
);
1913 dlg
->SetFont(propGrid
->GetFont()); // To allow entering chars of the same set as the propGrid
1915 // Multi-line text editor dialog.
1916 #if !wxPG_SMALL_SCREEN
1917 const int spacing
= 8;
1919 const int spacing
= 4;
1921 wxBoxSizer
* topsizer
= new wxBoxSizer( wxVERTICAL
);
1922 wxBoxSizer
* rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
1923 wxTextCtrl
* ed
= new wxTextCtrl(dlg
,11,value
,
1924 wxDefaultPosition
,wxDefaultSize
,wxTE_MULTILINE
);
1926 rowsizer
->Add( ed
, 1, wxEXPAND
|wxALL
, spacing
);
1927 topsizer
->Add( rowsizer
, 1, wxEXPAND
, 0 );
1928 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
1929 const int but_sz_flags
=
1930 wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxBOTTOM
|wxLEFT
|wxRIGHT
;
1931 rowsizer
->Add( new wxButton(dlg
,wxID_OK
,_("Ok")),
1932 0, but_sz_flags
, spacing
);
1933 rowsizer
->Add( new wxButton(dlg
,wxID_CANCEL
,_("Cancel")),
1934 0, but_sz_flags
, spacing
);
1935 topsizer
->Add( rowsizer
, 0, wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
, 0 );
1937 dlg
->SetSizer( topsizer
);
1938 topsizer
->SetSizeHints( dlg
);
1940 #if !wxPG_SMALL_SCREEN
1941 dlg
->SetSize(400,300);
1943 dlg
->Move( propGrid
->GetGoodEditorDialogPosition(prop
,dlg
->GetSize()) );
1946 int res
= dlg
->ShowModal();
1948 if ( res
== wxID_OK
)
1950 value
= ed
->GetValue();
1958 bool wxLongStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
1960 if ( m_value
!= text
)
1968 // -----------------------------------------------------------------------
1969 // wxArrayEditorDialog
1970 // -----------------------------------------------------------------------
1972 BEGIN_EVENT_TABLE(wxArrayEditorDialog
, wxDialog
)
1973 EVT_IDLE(wxArrayEditorDialog::OnIdle
)
1974 EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick
)
1975 EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick
)
1976 EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick
)
1977 EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick
)
1978 EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick
)
1979 EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick
)
1980 EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick
)
1981 //EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick)
1984 IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog
, wxDialog
)
1986 #include <wx/statline.h>
1988 // -----------------------------------------------------------------------
1990 void wxArrayEditorDialog::OnIdle(wxIdleEvent
& event
)
1993 // Do control focus detection here.
1996 wxWindow
* focused
= FindFocus();
1998 // This strange focus thing is a workaround for wxGTK wxListBox focus
2000 if ( m_curFocus
== 0 && focused
!= m_edValue
&&
2001 focused
!= m_butAdd
&& focused
!= m_butUpdate
&&
2002 m_lbStrings
->GetSelection() >= 0 )
2004 // ListBox was just focused.
2005 m_butAdd
->Enable(false);
2006 m_butUpdate
->Enable(false);
2007 m_butRemove
->Enable(true);
2008 m_butUp
->Enable(true);
2009 m_butDown
->Enable(true);
2012 else if ( (m_curFocus
== 1 && focused
== m_edValue
) /*|| m_curFocus == 2*/ )
2014 // TextCtrl was just focused.
2015 m_butAdd
->Enable(true);
2016 bool upd_enable
= false;
2017 if ( m_lbStrings
->GetCount() && m_lbStrings
->GetSelection() >= 0 )
2019 m_butUpdate
->Enable(upd_enable
);
2020 m_butRemove
->Enable(false);
2021 m_butUp
->Enable(false);
2022 m_butDown
->Enable(false);
2029 // -----------------------------------------------------------------------
2031 wxArrayEditorDialog::wxArrayEditorDialog()
2037 // -----------------------------------------------------------------------
2039 void wxArrayEditorDialog::Init()
2041 m_custBtText
= (const wxChar
*) NULL
;
2044 // -----------------------------------------------------------------------
2046 wxArrayEditorDialog::wxArrayEditorDialog( wxWindow
*parent
,
2047 const wxString
& message
,
2048 const wxString
& caption
,
2055 Create(parent
,message
,caption
,style
,pos
,sz
);
2058 // -----------------------------------------------------------------------
2060 bool wxArrayEditorDialog::Create( wxWindow
*parent
,
2061 const wxString
& message
,
2062 const wxString
& caption
,
2067 // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION
2068 // FIXME: This should be only a temporary fix.
2070 int useStyle
= wxCAPTION
;
2072 int useStyle
= style
;
2075 bool res
= wxDialog::Create(parent
, wxID_ANY
, caption
, pos
, sz
, useStyle
);
2077 SetFont(parent
->GetFont()); // To allow entering chars of the same set as the propGrid
2079 #if !wxPG_SMALL_SCREEN
2080 const int spacing
= 4;
2082 const int spacing
= 3;
2089 const int but_sz_flags
=
2090 wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
|wxALL
; //wxBOTTOM|wxLEFT|wxRIGHT;
2092 wxBoxSizer
* topsizer
= new wxBoxSizer( wxVERTICAL
);
2095 if ( message
.length() )
2096 topsizer
->Add( new wxStaticText(this,-1,message
),
2097 0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing
);
2100 wxBoxSizer
* rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2101 m_edValue
= new wxTextCtrl(this,21,wxEmptyString
,
2102 wxDefaultPosition
,wxDefaultSize
,wxTE_PROCESS_ENTER
);
2103 wxValidator
* validator
= GetTextCtrlValidator();
2106 m_edValue
->SetValidator( *validator
);
2109 rowsizer
->Add( m_edValue
,
2110 1, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxALL
, spacing
);
2113 m_butAdd
= new wxButton(this,22,_("Add"));
2114 rowsizer
->Add( m_butAdd
,
2115 0, wxALIGN_LEFT
|wxALIGN_CENTRE_VERTICAL
|wxTOP
|wxBOTTOM
|wxRIGHT
, spacing
);
2116 topsizer
->Add( rowsizer
, 0, wxEXPAND
, spacing
);
2119 topsizer
->Add( new wxStaticLine(this,-1),
2120 0, wxEXPAND
|wxBOTTOM
|wxLEFT
|wxRIGHT
, spacing
);
2122 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2125 m_lbStrings
= new wxListBox(this, 24, wxDefaultPosition
, wxDefaultSize
);
2127 for ( i
=0; i
<ArrayGetCount(); i
++ )
2128 m_lbStrings
->Append( ArrayGet(i
) );
2129 rowsizer
->Add( m_lbStrings
, 1, wxEXPAND
|wxRIGHT
, spacing
);
2131 // Manipulator buttons
2132 wxBoxSizer
* colsizer
= new wxBoxSizer( wxVERTICAL
);
2133 m_butCustom
= (wxButton
*) NULL
;
2136 m_butCustom
= new wxButton(this,28,::wxGetTranslation(m_custBtText
));
2137 colsizer
->Add( m_butCustom
,
2138 0, wxALIGN_CENTER
|wxTOP
/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/,
2141 m_butUpdate
= new wxButton(this,27,_("Update"));
2142 colsizer
->Add( m_butUpdate
,
2143 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2144 m_butRemove
= new wxButton(this,23,_("Remove"));
2145 colsizer
->Add( m_butRemove
,
2146 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2147 m_butUp
= new wxButton(this,25,_("Up"));
2148 colsizer
->Add( m_butUp
,
2149 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2150 m_butDown
= new wxButton(this,26,_("Down"));
2151 colsizer
->Add( m_butDown
,
2152 0, wxALIGN_CENTER
|wxTOP
, spacing
);
2153 rowsizer
->Add( colsizer
, 0, 0, spacing
);
2155 topsizer
->Add( rowsizer
, 1, wxLEFT
|wxRIGHT
|wxEXPAND
, spacing
);
2158 topsizer
->Add( new wxStaticLine(this,-1),
2159 0, wxEXPAND
|wxTOP
|wxLEFT
|wxRIGHT
, spacing
);
2162 rowsizer
= new wxBoxSizer( wxHORIZONTAL
);
2164 const int but_sz_flags =
2165 wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT;
2167 rowsizer
->Add( new wxButton(this,wxID_OK
,_("Ok")),
2168 0, but_sz_flags
, spacing
);
2169 rowsizer
->Add( new wxButton(this,wxID_CANCEL
,_("Cancel")),
2170 0, but_sz_flags
, spacing
);
2171 topsizer
->Add( rowsizer
, 0, wxALIGN_RIGHT
|wxALIGN_CENTRE_VERTICAL
, 0 );
2173 m_edValue
->SetFocus();
2175 SetSizer( topsizer
);
2176 topsizer
->SetSizeHints( this );
2178 #if !wxPG_SMALL_SCREEN
2179 if ( sz
.x
== wxDefaultSize
.x
&&
2180 sz
.y
== wxDefaultSize
.y
)
2181 SetSize( wxSize(275,360) );
2189 // -----------------------------------------------------------------------
2191 void wxArrayEditorDialog::OnAddClick(wxCommandEvent
& )
2193 wxString text
= m_edValue
->GetValue();
2194 if ( text
.length() )
2196 if ( ArrayInsert( text
, -1 ) )
2198 m_lbStrings
->Append( text
);
2205 // -----------------------------------------------------------------------
2207 void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent
& )
2209 int index
= m_lbStrings
->GetSelection();
2212 ArrayRemoveAt( index
);
2213 m_lbStrings
->Delete ( index
);
2218 // -----------------------------------------------------------------------
2220 void wxArrayEditorDialog::OnUpClick(wxCommandEvent
& )
2222 int index
= m_lbStrings
->GetSelection();
2225 ArraySwap(index
-1,index
);
2226 /*wxString old_str = m_array[index-1];
2227 wxString new_str = m_array[index];
2228 m_array[index-1] = new_str;
2229 m_array[index] = old_str;*/
2230 m_lbStrings
->SetString ( index
-1, ArrayGet(index
-1) );
2231 m_lbStrings
->SetString ( index
, ArrayGet(index
) );
2232 m_lbStrings
->SetSelection ( index
-1 );
2237 // -----------------------------------------------------------------------
2239 void wxArrayEditorDialog::OnDownClick(wxCommandEvent
& )
2241 int index
= m_lbStrings
->GetSelection();
2242 int lastStringIndex
= ((int) m_lbStrings
->GetCount()) - 1;
2243 if ( index
>= 0 && index
< lastStringIndex
)
2245 ArraySwap(index
,index
+1);
2246 /*wxString old_str = m_array[index+1];
2247 wxString new_str = m_array[index];
2248 m_array[index+1] = new_str;
2249 m_array[index] = old_str;*/
2250 m_lbStrings
->SetString ( index
+1, ArrayGet(index
+1) );
2251 m_lbStrings
->SetString ( index
, ArrayGet(index
) );
2252 m_lbStrings
->SetSelection ( index
+1 );
2257 // -----------------------------------------------------------------------
2259 void wxArrayEditorDialog::OnUpdateClick(wxCommandEvent
& )
2261 int index
= m_lbStrings
->GetSelection();
2264 wxString str
= m_edValue
->GetValue();
2265 if ( ArraySet(index
,str
) )
2267 m_lbStrings
->SetString ( index
, str
);
2268 //m_array[index] = str;
2274 // -----------------------------------------------------------------------
2276 void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent
& )
2278 int index
= m_lbStrings
->GetSelection();
2281 m_edValue
->SetValue( m_lbStrings
->GetString(index
) );
2285 // -----------------------------------------------------------------------
2286 // wxPGArrayStringEditorDialog
2287 // -----------------------------------------------------------------------
2289 IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog
, wxArrayEditorDialog
)
2291 BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog
, wxArrayEditorDialog
)
2292 EVT_BUTTON(28, wxPGArrayStringEditorDialog::OnCustomEditClick
)
2295 // -----------------------------------------------------------------------
2297 wxString
wxPGArrayStringEditorDialog::ArrayGet( size_t index
)
2299 return m_array
[index
];
2302 size_t wxPGArrayStringEditorDialog::ArrayGetCount()
2304 return m_array
.size();
2307 bool wxPGArrayStringEditorDialog::ArrayInsert( const wxString
& str
, int index
)
2312 m_array
.Insert(str
,index
);
2316 bool wxPGArrayStringEditorDialog::ArraySet( size_t index
, const wxString
& str
)
2318 m_array
[index
] = str
;
2322 void wxPGArrayStringEditorDialog::ArrayRemoveAt( int index
)
2324 m_array
.RemoveAt(index
);
2327 void wxPGArrayStringEditorDialog::ArraySwap( size_t first
, size_t second
)
2329 wxString old_str
= m_array
[first
];
2330 wxString new_str
= m_array
[second
];
2331 m_array
[first
] = new_str
;
2332 m_array
[second
] = old_str
;
2335 wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog()
2336 : wxArrayEditorDialog()
2341 void wxPGArrayStringEditorDialog::Init()
2343 m_pCallingClass
= (wxArrayStringProperty
*) NULL
;
2346 void wxPGArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent
& )
2348 wxASSERT( m_pCallingClass
);
2349 wxString str
= m_edValue
->GetValue();
2350 if ( m_pCallingClass
->OnCustomStringEdit(m_parent
,str
) )
2352 //m_edValue->SetValue ( str );
2353 m_lbStrings
->Append ( str
);
2354 m_array
.Add ( str
);
2359 // -----------------------------------------------------------------------
2360 // wxArrayStringProperty
2361 // -----------------------------------------------------------------------
2363 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty
, // Property name
2364 wxPGProperty
, // Property we inherit from
2365 wxArrayString
, // Value type name
2366 const wxArrayString
&, // Value type, as given in constructor
2367 TextCtrlAndButton
) // Initial editor
2369 wxArrayStringProperty::wxArrayStringProperty( const wxString
& label
,
2370 const wxString
& name
,
2371 const wxArrayString
& array
)
2372 : wxPGProperty(label
,name
)
2377 wxArrayStringProperty::~wxArrayStringProperty() { }
2379 void wxArrayStringProperty::OnSetValue()
2381 GenerateValueAsString();
2384 wxString
wxArrayStringProperty::GetValueAsString( int WXUNUSED(argFlags
) ) const
2389 // Converts wxArrayString to a string separated by delimeters and spaces.
2390 // preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash
2392 void wxPropertyGrid::ArrayStringToString( wxString
& dst
, const wxArrayString
& src
,
2393 wxChar preDelim
, wxChar postDelim
,
2399 unsigned int itemCount
= src
.size();
2407 else if ( (flags
& 1) )
2409 preas
[0] = preDelim
;
2416 dst
.append( preas
);
2418 wxASSERT( postDelim
);
2419 wxString
postDelimStr(postDelim
);
2420 //wxString preDelimStr(preDelim);
2422 for ( i
= 0; i
< itemCount
; i
++ )
2424 wxString
str( src
.Item(i
) );
2426 // Do some character conversion.
2427 // Convertes \ to \\ and <preDelim> to \<preDelim>
2428 // Useful when preDelim and postDelim are "\"".
2431 str
.Replace( wxS("\\"), wxS("\\\\"), true );
2433 str
.Replace( preas
, pdr
, true );
2438 if ( i
< (itemCount
-1) )
2440 dst
.append( postDelimStr
);
2441 dst
.append( wxS(" ") );
2442 dst
.append( preas
);
2444 else if ( preDelim
)
2445 dst
.append( postDelimStr
);
2449 #define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \
2450 wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxS('"'),wxS('"'),1);
2452 void wxArrayStringProperty::GenerateValueAsString()
2454 wxArrayString arr
= m_value
.GetArrayString();
2455 ARRSTRPROP_ARRAY_TO_STRING(m_display
, arr
)
2458 // Default implementation doesn't do anything.
2459 bool wxArrayStringProperty::OnCustomStringEdit( wxWindow
*, wxString
& )
2464 wxArrayEditorDialog
* wxArrayStringProperty::CreateEditorDialog()
2466 return new wxPGArrayStringEditorDialog();
2469 bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid
* propGrid
,
2470 wxWindow
* WXUNUSED(primaryCtrl
),
2474 PrepareValueForDialogEditing(propGrid
);
2476 if ( !propGrid
->EditorValidate() )
2479 // Create editor dialog.
2480 wxArrayEditorDialog
* dlg
= CreateEditorDialog();
2481 #if wxUSE_VALIDATORS
2482 wxValidator
* validator
= GetValidator();
2483 wxPGInDialogValidator dialogValidator
;
2486 wxPGArrayStringEditorDialog
* strEdDlg
= wxDynamicCast(dlg
, wxPGArrayStringEditorDialog
);
2489 strEdDlg
->SetCustomButton(cbt
, this);
2491 dlg
->SetDialogValue( wxVariant(m_value
) );
2492 dlg
->Create(propGrid
, wxEmptyString
, m_label
);
2494 #if !wxPG_SMALL_SCREEN
2495 dlg
->Move( propGrid
->GetGoodEditorDialogPosition(this,dlg
->GetSize()) );
2504 int res
= dlg
->ShowModal();
2506 if ( res
== wxID_OK
&& dlg
->IsModified() )
2508 wxVariant value
= dlg
->GetDialogValue();
2509 if ( !value
.IsNull() )
2511 wxArrayString actualValue
= value
.GetArrayString();
2513 ARRSTRPROP_ARRAY_TO_STRING(tempStr
, actualValue
)
2514 #if wxUSE_VALIDATORS
2515 if ( dialogValidator
.DoValidate( propGrid
, validator
, tempStr
) )
2518 SetValueInEvent( actualValue
);
2535 bool wxArrayStringProperty::OnEvent( wxPropertyGrid
* propGrid
,
2539 if ( propGrid
->IsMainButtonEvent(event
) )
2540 return OnButtonClick(propGrid
,primary
,(const wxChar
*) NULL
);
2544 bool wxArrayStringProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
2548 WX_PG_TOKENIZER2_BEGIN(text
,wxS('"'))
2550 // Need to replace backslashes with empty characters
2551 // (opposite what is done in GenerateValueString).
2552 token
.Replace ( wxS("\\"), wxEmptyString
, true );
2556 WX_PG_TOKENIZER2_END()
2563 // -----------------------------------------------------------------------
2564 // wxPGInDialogValidator
2565 // -----------------------------------------------------------------------
2567 #if wxUSE_VALIDATORS
2568 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* propGrid
,
2569 wxValidator
* validator
,
2570 const wxString
& value
)
2575 wxTextCtrl
* tc
= m_textCtrl
;
2580 tc
= new wxTextCtrl( propGrid
, wxPG_SUBID_TEMP1
, wxEmptyString
,
2581 wxPoint(30000,30000));
2588 tc
->SetValue(value
);
2590 validator
->SetWindow(tc
);
2591 bool res
= validator
->Validate(propGrid
);
2596 bool wxPGInDialogValidator::DoValidate( wxPropertyGrid
* WXUNUSED(propGrid
),
2597 wxValidator
* WXUNUSED(validator
),
2598 const wxString
& WXUNUSED(value
) )
2604 // -----------------------------------------------------------------------