1
/////////////////////////////////////////////////////////////////////////////
3
// Purpose: Basic Property Classes
4
// Author: Jaakko Salli
6
// Created: May-14-2004
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
#include <wx/propgrid/propdev.h>
58
#define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc.
61
// -----------------------------------------------------------------------
63
// -----------------------------------------------------------------------
65
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty,wxPGProperty,
66
wxString,const wxString&,TextCtrl)
68
wxStringProperty::wxStringProperty( const wxString& label,
70
const wxString& value )
71
: wxPGProperty(label,name)
76
void wxStringProperty::OnSetValue()
78
if ( !m_value.IsNull() && m_value.GetString() == wxT("<composed>") )
79
SetFlag(wxPG_PROP_COMPOSED_VALUE);
81
if ( HasFlag(wxPG_PROP_COMPOSED_VALUE) )
84
GenerateComposedValue(s, 0);
89
wxStringProperty::~wxStringProperty() { }
91
wxString wxStringProperty::GetValueAsString( int argFlags ) const
93
wxString s = m_value.GetString();
95
if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE) )
97
// Value stored in m_value is non-editable, non-full value
98
if ( (argFlags & wxPG_FULL_VALUE) || (argFlags & wxPG_EDITABLE_VALUE) )
99
GenerateComposedValue(s, argFlags);
104
// If string is password and value is for visual purposes,
105
// then return asterisks instead the actual string.
106
if ( (m_flags & wxPG_PROP_PASSWORD) && !(argFlags & (wxPG_FULL_VALUE|wxPG_EDITABLE_VALUE)) )
107
return wxString(wxChar('*'), s.Length());
112
bool wxStringProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
114
if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE) )
115
return wxPGProperty::StringToValue(variant, text, argFlags);
117
if ( m_value.IsNull() || m_value.GetString() != text )
126
bool wxStringProperty::DoSetAttribute( const wxString& name, wxVariant& value )
128
if ( name == wxPG_STRING_PASSWORD )
130
m_flags &= ~(wxPG_PROP_PASSWORD);
131
if ( wxPGVariantToInt(value) ) m_flags |= wxPG_PROP_PASSWORD;
138
// -----------------------------------------------------------------------
140
#ifndef wxHAS_STRTOLL
141
#if wxCHECK_VERSION(2,9,0)
142
#define wxHAS_STRTOLL
148
#define wxINT64_MAX LLONG_MAX
149
#define wxINT64_MIN LLONG_MIN
151
#define wxINT64_MAX wxLL(9223372036854775807)
152
#define wxINT64_MIN (wxLL(-9223372036854775807)-1)
157
#define wxUINT64_MAX wxULL(0xFFFFFFFFFFFFFFFF)
158
#define wxUINT64_MIN wxULL(0)
161
#ifndef wxHAS_STRTOLL
164
#define wxSET_ERRNO(A) errno = A
169
static wxULongLong_t wxStrtoullBase(const wxChar* nptr, wxChar** endptr, int base, wxChar* sign)
171
wxULongLong_t sum = 0;
172
wxString wxstr(nptr);
173
wxString::const_iterator i = wxstr.begin();
174
wxString::const_iterator end = wxstr.end();
177
while ( i != end && wxIsspace(*i) ) i++;
184
if ( c == wxT('+') || c == wxT('-') )
192
if ( i != end && *i == wxT('0') )
197
if ( *i == wxT('x') && (base == 16 || base == 0) )
205
*endptr = (wxChar*) nptr;
217
for ( ; i != end; i++ )
227
n = wxTolower(c) - wxT('a') + 10;
232
if ( n >= (unsigned int)base )
233
// Invalid character (for this base)
236
wxULongLong_t prevsum = sum;
237
sum = (sum * base) + n;
248
*endptr = (wxChar*)(nptr + (i - wxstr.begin()));
254
wxULongLong_t wxStrtoull(const wxChar* nptr, wxChar** endptr, int base)
257
wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
259
if ( sign == wxT('-') )
268
wxLongLong_t wxStrtoll(const wxChar* nptr, wxChar** endptr, int base)
271
wxULongLong_t uval = wxStrtoullBase(nptr, endptr, base, &sign);
272
wxLongLong_t val = 0;
274
if ( sign == wxT('-') )
276
if ( uval <= wxULL(wxINT64_MAX+1) )
278
if ( uval == wxULL(wxINT64_MAX+1))
279
val = -((wxLongLong_t)wxINT64_MAX) - 1;
281
val = -((wxLongLong_t)uval);
288
else if ( uval <= wxINT64_MAX )
300
bool wxPGStringToLongLong(const wxString s, wxLongLong_t* val, int base)
304
*val = wxStrtoll(s.c_str(), &endptr, base);
305
return (errno == 0 && *endptr == wxT('\0'));
308
bool wxPGStringToULongLong(const wxString s, wxULongLong_t* val, int base)
312
*val = wxStrtoull(s.c_str(), &endptr, base);
313
return (errno == 0 && *endptr == wxT('\0'));
318
bool wxPGStringToLongLong(const wxString s, wxLongLong_t* val, int base)
320
return s.ToLongLong(val, base);
323
bool wxPGStringToULongLong(const wxString s, wxULongLong_t* val, int base)
325
return s.ToULongLong(val, base);
328
#endif // !wxHAS_STRTOLL
330
// -----------------------------------------------------------------------
332
// -----------------------------------------------------------------------
334
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty,wxPGProperty,
337
wxIntProperty::wxIntProperty( const wxString& label, const wxString& name,
338
long value ) : wxPGProperty(label,name)
343
wxIntProperty::wxIntProperty( const wxString& label, const wxString& name,
344
const wxLongLong& value ) : wxPGProperty(label,name)
346
SetValue(wxLongLongToVariant(value));
349
wxIntProperty::~wxIntProperty() { }
351
wxString wxIntProperty::GetValueAsString( int ) const
353
if ( wxPGIsVariantType(m_value, long) )
354
return wxString::Format(wxT("%li"),m_value.GetLong());
356
wxLongLong* ll = &wxLongLongFromVariant(m_value);
358
return ll->ToString();
360
return wxEmptyString;
363
bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
368
if ( text.length() == 0 )
374
// We know it is a number, but let's still check
376
if ( text.IsNumber() )
378
// Remove leading zeroes, so that the number is not interpreted as octal
379
wxString::const_iterator i = text.begin();
380
wxString::const_iterator iMax = text.end() - 1; // Let's allow one, last zero though
382
int firstNonZeroPos = 0;
384
for ( ; i != iMax; i++ )
387
if ( c != wxT('0') && c != wxT(' ') )
392
wxString useText = text.substr(firstNonZeroPos, text.length() - firstNonZeroPos);
394
bool isPrevLong = wxPGIsVariantType(variant, long);
396
wxLongLong_t value64 = 0;
398
if ( wxPGStringToLongLong(useText, &value64, 10) &&
399
( value64 >= INT_MAX || value64 <= INT_MIN )
402
wxLongLong* _m_value64 = &wxLongLongFromVariant(m_value);
403
if ( isPrevLong || !_m_value64 || _m_value64->GetValue() != value64 )
405
variant = wxLongLongToVariant(value64);
410
if ( useText.ToLong( &value32, 0 ) )
412
if ( !isPrevLong || m_value.IsNull() || m_value.GetLong() != value32 )
419
else if ( argFlags & wxPG_REPORT_ERROR )
425
bool wxIntProperty::IntToValue( wxVariant& variant, int value, int WXUNUSED(argFlags) ) const
427
if ( !wxPGIsVariantType(variant, long) || variant.GetLong() != value )
429
variant = (long)value;
435
bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& value, wxPGValidationInfo* pValidationInfo, int mode )
438
wxLongLong_t min = wxINT64_MIN;
439
wxLongLong_t max = wxINT64_MAX;
444
variant = property->GetAttribute(wxPGGlobalVars->m_strMin);
445
if ( !variant.IsNull() )
447
wxPGVariantToLongLong(variant, &min);
451
variant = property->GetAttribute(wxPGGlobalVars->m_strMax);
452
if ( !variant.IsNull() )
454
wxPGVariantToLongLong(variant, &max);
462
if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
463
pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %lld or higher"),min);
464
else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
467
value = max - (min - value);
476
if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
477
pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %lld or higher"),min);
478
else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
481
value = min + (value - max);
488
bool wxIntProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const
491
if ( wxPGVariantToLongLong(value, &ll) )
492
return DoValidation(this, ll, &validationInfo, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE);
496
wxValidator* wxIntProperty::GetClassValidator()
499
WX_PG_DOGETVALIDATOR_ENTRY()
501
// Atleast wxPython 2.6.2.1 required that the string argument is given
503
wxTextValidator* validator = new wxTextValidator(wxFILTER_NUMERIC,&v);
505
WX_PG_DOGETVALIDATOR_EXIT(validator)
511
wxValidator* wxIntProperty::DoGetValidator() const
513
return GetClassValidator();
516
// -----------------------------------------------------------------------
518
// -----------------------------------------------------------------------
521
#define wxPG_UINT_TEMPLATE_MAX 8
523
static const wxChar* gs_uintTemplates32[wxPG_UINT_TEMPLATE_MAX] = {
524
wxT("%x"),wxT("0x%x"),wxT("$%x"),
525
wxT("%X"),wxT("0x%X"),wxT("$%X"),
529
static const wxChar* gs_uintTemplates64[wxPG_UINT_TEMPLATE_MAX] = {
530
wxT("%") wxLongLongFmtSpec wxT("x"),
531
wxT("0x%") wxLongLongFmtSpec wxT("x"),
532
wxT("$%") wxLongLongFmtSpec wxT("x"),
533
wxT("%") wxLongLongFmtSpec wxT("X"),
534
wxT("0x%") wxLongLongFmtSpec wxT("X"),
535
wxT("$%") wxLongLongFmtSpec wxT("X"),
536
wxT("%") wxLongLongFmtSpec wxT("u"),
537
wxT("%") wxLongLongFmtSpec wxT("o")
540
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty,wxPGProperty,
541
long,unsigned long,TextCtrl)
543
void wxUIntProperty::Init()
545
m_base = 6; // This is magic number for dec base (must be same as in setattribute)
547
m_prefix = wxPG_PREFIX_NONE;
550
wxUIntProperty::wxUIntProperty( const wxString& label, const wxString& name,
551
unsigned long value ) : wxPGProperty(label,name)
554
SetValue((long)value);
557
wxUIntProperty::wxUIntProperty( const wxString& label, const wxString& name,
558
const wxULongLong& value ) : wxPGProperty(label,name)
561
SetValue(wxULongLongToVariant(value));
564
wxUIntProperty::~wxUIntProperty() { }
566
wxString wxUIntProperty::GetValueAsString( int ) const
568
size_t index = m_base + m_prefix;
569
if ( index >= wxPG_UINT_TEMPLATE_MAX )
570
index = wxPG_BASE_DEC;
572
if ( wxPGIsVariantType(m_value, long) )
573
return wxString::Format(gs_uintTemplates32[index],(unsigned long)m_value.GetLong());
575
return wxString::Format(gs_uintTemplates64[index],wxULongLongFromVariant(m_value).GetValue());
578
bool wxUIntProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const
580
//long unsigned value32 = 0;
581
bool isPrevLong = wxPGIsVariantType(variant, long);
583
if ( text.length() == 0 )
590
if ( text[0] == wxT('$') )
593
wxULongLong_t value64 = 0;
594
wxString s = text.substr(start, text.length() - start);
596
if ( wxPGStringToULongLong(s, &value64, (unsigned int)m_realBase) )
598
if ( value64 >= LONG_MAX )
600
wxULongLong* _m_value64 = &wxULongLongFromVariant(m_value);
601
if ( isPrevLong || !_m_value64 || _m_value64->GetValue() != value64 )
603
variant = wxULongLongToVariant(value64);
609
unsigned long value32 = wxLongLong(value64).GetLo();
610
if ( !isPrevLong || m_value.GetLong() != (long)value32 )
612
variant = (long)value32;
621
bool wxUIntProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
623
if ( m_value.IsNull() || m_value != (long)number )
625
variant = (long)number;
631
bool wxUIntProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const
635
if ( wxPGVariantToULongLong(value, &ll) )
637
wxULongLong_t min = wxUINT64_MIN;
638
wxULongLong_t max = wxUINT64_MAX;
641
variant = GetAttribute(wxPGGlobalVars->m_strMin);
642
if ( !variant.IsNull() )
644
wxPGVariantToULongLong(variant, &min);
647
validationInfo.m_failureMessage = wxString::Format(_("Value must be %llu or higher"),min);
651
variant = GetAttribute(wxPGGlobalVars->m_strMax);
652
if ( !variant.IsNull() )
654
wxPGVariantToULongLong(variant, &max);
657
validationInfo.m_failureMessage = wxString::Format(_("Value must be %llu or less"),max);
665
bool wxUIntProperty::DoSetAttribute( const wxString& name, wxVariant& value )
667
if ( name == wxPG_UINT_BASE )
669
int val = value.GetLong();
671
m_realBase = (wxByte) val;
672
if ( m_realBase > 16 )
676
// Translate logical base to a template array index
678
if ( val == wxPG_BASE_HEX )
680
else if ( val == wxPG_BASE_DEC )
682
else if ( val == wxPG_BASE_HEXL )
686
else if ( name == wxPG_UINT_PREFIX )
688
m_prefix = (wxByte) value.GetLong();
694
// -----------------------------------------------------------------------
696
// -----------------------------------------------------------------------
698
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty,wxPGProperty,
699
double,double,TextCtrl)
701
wxFloatProperty::wxFloatProperty( const wxString& label,
702
const wxString& name,
704
: wxPGProperty(label,name)
710
wxFloatProperty::~wxFloatProperty() { }
712
// This helper method provides standard way for floating point-using
713
// properties to convert values to string.
714
void wxPropertyGrid::DoubleToString(wxString& target,
718
wxString* precTemplate)
720
if ( precision >= 0 )
724
precTemplate = &text1;
726
if ( !precTemplate->length() )
728
*precTemplate = wxT("%.");
729
*precTemplate << wxString::Format( wxT("%i"), precision );
730
*precTemplate << wxT('f');
733
target.Printf( precTemplate->c_str(), value );
737
target.Printf( wxT("%f"), value );
740
if ( removeZeroes && precision != 0 && target.length() )
742
// Remove excess zeroes (do not remove this code just yet,
743
// since sprintf can't do the same consistently across platforms).
744
wxString::const_iterator i = target.end() - 1;
745
size_t new_len = target.length() - 1;
747
for ( ; i != target.begin(); i-- )
749
if ( wxPGGetIterChar(target, i) != wxT('0') )
754
wxChar cur_char = wxPGGetIterChar(target, i);
755
if ( cur_char != wxT('.') && cur_char != wxT(',') )
758
if ( new_len != target.length() )
759
target.resize(new_len);
763
wxString wxFloatProperty::GetValueAsString( int argFlags ) const
766
if ( !m_value.IsNull() )
768
wxPropertyGrid::DoubleToString(text,
771
!(argFlags & wxPG_FULL_VALUE),
777
bool wxFloatProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
782
if ( text.length() == 0 )
788
bool res = text.ToDouble(&value);
791
if ( m_value.IsNull() || m_value != value )
797
else if ( argFlags & wxPG_REPORT_ERROR )
803
bool wxFloatProperty::DoValidation( const wxPGProperty* property, double& value, wxPGValidationInfo* pValidationInfo, int mode )
806
double min = (double)wxINT64_MIN;
807
double max = (double)wxINT64_MAX;
812
variant = property->GetAttribute(wxPGGlobalVars->m_strMin);
813
if ( !variant.IsNull() )
815
wxPGVariantToDouble(variant, &min);
819
variant = property->GetAttribute(wxPGGlobalVars->m_strMax);
820
if ( !variant.IsNull() )
822
wxPGVariantToDouble(variant, &max);
830
if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
831
pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %f or higher"),min);
832
else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
835
value = max - (min - value);
842
wxPGVariantToDouble(variant, &max);
845
if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE )
846
pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %f or less"),max);
847
else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE )
850
value = min + (value - max);
857
bool wxFloatProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const
860
if ( wxPGVariantToDouble(value, &fpv) )
861
return DoValidation(this, fpv, &validationInfo, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE);
865
bool wxFloatProperty::DoSetAttribute( const wxString& name, wxVariant& value )
867
if ( name == wxPG_FLOAT_PRECISION )
869
m_precision = value.GetLong();
875
wxValidator* wxFloatProperty::DoGetValidator() const
877
return wxIntProperty::GetClassValidator();
880
// -----------------------------------------------------------------------
882
// -----------------------------------------------------------------------
884
// We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since
885
// there is a custom GetEditorClass.
887
IMPLEMENT_DYNAMIC_CLASS(wxBoolProperty, wxPGProperty)
889
const wxPGEditor* wxBoolProperty::DoGetEditorClass() const
891
// Select correct editor control.
892
#if wxPG_INCLUDE_CHECKBOX
893
if ( !(m_flags & wxPG_PROP_USE_CHECKBOX) )
894
return wxPG_EDITOR(Choice);
895
return wxPG_EDITOR(CheckBox);
897
return wxPG_EDITOR(Choice);
901
wxBoolProperty::wxBoolProperty( const wxString& label, const wxString& name, bool value ) :
902
wxPGProperty(label,name)
904
SetValue(wxPGVariant_Bool(value));
906
m_flags |= wxPG_PROP_USE_DCC;
909
wxBoolProperty::~wxBoolProperty() { }
911
wxString wxBoolProperty::GetValueAsString( int argFlags ) const
913
bool value = m_value.GetBool();
915
// As a fragment of composite string value,
916
// make it a little more readable.
917
if ( argFlags & wxPG_COMPOSITE_FRAGMENT )
925
if ( argFlags & wxPG_UNEDITABLE_COMPOSITE_FRAGMENT )
926
return wxEmptyString;
928
const wxChar* notFmt;
929
if ( wxPGGlobalVars->m_autoGetTranslation )
930
notFmt = _("Not %s");
932
notFmt = wxT("Not %s");
934
return wxString::Format(notFmt,m_label.c_str());
938
if ( !(argFlags & wxPG_FULL_VALUE) )
940
return wxPGGlobalVars->m_boolChoices[value?1:0].GetText();
945
if (value) text = wxT("true");
946
else text = wxT("false");
951
int wxBoolProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo )
954
choiceinfo->m_choices = &wxPGGlobalVars->m_boolChoices;
956
if ( IsValueUnspecified() )
959
return m_value.GetBool()?1:0;
962
bool wxBoolProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const
965
if ( text.CmpNoCase(wxPGGlobalVars->m_boolChoices[1].GetText()) == 0 ||
966
text.CmpNoCase(wxT("true")) == 0 ||
967
text.CmpNoCase(m_label) == 0 )
970
if ( text.length() == 0 )
976
if ( m_value.IsNull() || (m_value.GetBool() && !value) || (!m_value.GetBool() && value) )
978
variant = wxPGVariant_Bool(value);
984
bool wxBoolProperty::IntToValue( wxVariant& variant, int value, int ) const
986
bool boolValue = value ? true : false;
988
if ( m_value.IsNull() || boolValue != m_value.GetBool() )
990
variant = wxPGVariant_Bool(boolValue);
996
bool wxBoolProperty::DoSetAttribute( const wxString& name, wxVariant& value )
998
#if wxPG_INCLUDE_CHECKBOX
999
if ( name == wxPG_BOOL_USE_CHECKBOX )
1001
int ival = wxPGVariantToInt(value);
1003
m_flags |= wxPG_PROP_USE_CHECKBOX;
1005
m_flags &= ~(wxPG_PROP_USE_CHECKBOX);
1009
if ( name == wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING )
1011
int ival = wxPGVariantToInt(value);
1013
m_flags |= wxPG_PROP_USE_DCC;
1015
m_flags &= ~(wxPG_PROP_USE_DCC);
1021
// -----------------------------------------------------------------------
1022
// wxBaseEnumProperty
1023
// -----------------------------------------------------------------------
1025
int wxBaseEnumProperty::ms_nextIndex = -2;
1027
wxBaseEnumProperty::wxBaseEnumProperty( const wxString& label, const wxString& name )
1028
: wxPGProperty(label,name)
1030
m_value = wxPGVariant_Zero;
1033
/** If has values array, then returns number at index with value -
1034
otherwise just returns the value.
1036
int wxBaseEnumProperty::GetIndexForValue( int value ) const
1041
void wxBaseEnumProperty::OnSetValue()
1043
if ( wxPGIsVariantType(m_value, long) )
1044
ValueFromInt_( m_value, m_value.GetLong(), wxPG_FULL_VALUE );
1045
else if ( wxPGIsVariantType(m_value, string) )
1046
ValueFromString_( m_value, m_value.GetString(), 0 );
1050
if ( ms_nextIndex != -2 )
1052
m_index = ms_nextIndex;
1057
bool wxBaseEnumProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& WXUNUSED(validationInfo) ) const
1059
// Make sure string value is in the list,
1060
// unless property has string as preferred value type
1061
// To reduce code size, use conversion here as well
1062
if ( wxPGIsVariantType(value, string) &&
1063
!this->IsKindOf(CLASSINFO(wxEditEnumProperty)) )
1064
return ValueFromString_( value, value.GetString(), wxPG_PROPERTY_SPECIFIC );
1069
wxString wxBaseEnumProperty::GetValueAsString( int ) const
1071
if ( wxPGIsVariantType(m_value, string) )
1072
return m_value.GetString();
1077
const wxString* pstr = GetEntry( m_index, &unusedVal );
1082
return wxEmptyString;
1085
bool wxBaseEnumProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
1087
return ValueFromString_( variant, text, argFlags );
1090
bool wxBaseEnumProperty::IntToValue( wxVariant& variant, int intVal, int argFlags ) const
1092
return ValueFromInt_( variant, intVal, argFlags );
1095
bool wxBaseEnumProperty::ValueFromString_( wxVariant& value, const wxString& text, int argFlags ) const
1098
const wxString* entryLabel;
1103
entryLabel = GetEntry(i, &entryValue);
1104
while ( entryLabel )
1106
if ( text.CmpNoCase(*entryLabel) == 0 )
1109
useValue = (long)entryValue;
1114
entryLabel = GetEntry(i, &entryValue);
1117
bool asText = false;
1119
bool isEdit = this->IsKindOf(CLASSINFO(wxEditEnumProperty));
1121
// If text not any of the choices, store as text instead
1122
// (but only if we are wxEditEnumProperty)
1123
if ( useIndex == -1 &&
1129
int setAsNextIndex = -2;
1130
int curIndex = GetIndex();
1134
setAsNextIndex = -1;
1137
else if ( curIndex != useIndex )
1139
if ( useIndex != -1 )
1141
setAsNextIndex = useIndex;
1142
value = (long)useValue;
1146
setAsNextIndex = -1;
1147
value = wxPGVariant_MinusOne;
1151
if ( setAsNextIndex != -2 )
1153
// If wxPG_PROPERTY_SPECIFIC is set, then this is done for
1154
// validation purposes only, and index must not be changed
1155
if ( !(argFlags & wxPG_PROPERTY_SPECIFIC) )
1156
ms_nextIndex = setAsNextIndex;
1158
if ( isEdit || setAsNextIndex != -1 )
1166
bool wxBaseEnumProperty::ValueFromInt_( wxVariant& variant, int intVal, int argFlags ) const
1168
// If wxPG_FULL_VALUE is *not* in argFlags, then intVal is index from combo box.
1170
int curIndex = GetIndex();
1173
if ( argFlags & wxPG_FULL_VALUE )
1175
ms_nextIndex = GetIndexForValue( intVal );
1179
if ( curIndex != intVal )
1181
ms_nextIndex = intVal;
1185
if ( ms_nextIndex != -2 )
1187
if ( !(argFlags & wxPG_FULL_VALUE) )
1188
GetEntry(intVal, &intVal);
1190
variant = (long)intVal;
1199
wxBaseEnumProperty::OnValidationFailure( wxVariant& WXUNUSED(pendingValue) )
1205
void wxBaseEnumProperty::SetIndex( int index )
1211
int wxBaseEnumProperty::GetIndex() const
1213
if ( m_value.IsNull() )
1216
if ( ms_nextIndex != -2 )
1217
return ms_nextIndex;
1222
// -----------------------------------------------------------------------
1224
// -----------------------------------------------------------------------
1226
IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty, wxPGProperty)
1228
WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty,long,Choice)
1230
wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1231
const long* values, int value ) : wxBaseEnumProperty(label,name)
1237
m_choices.Add(labels,values);
1239
if ( GetItemCount() )
1240
SetValue( (long)value );
1244
wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1245
const long* values, wxPGChoices* choicesCache, int value )
1246
: wxBaseEnumProperty(label,name)
1250
wxASSERT( choicesCache );
1252
if ( choicesCache->IsOk() )
1254
m_choices.Assign( *choicesCache );
1255
m_value = wxPGVariant_Zero;
1259
m_choices.Add(labels,values);
1261
if ( GetItemCount() )
1262
SetValue( (long)value );
1266
wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name,
1267
const wxArrayString& labels, const wxArrayInt& values, int value ) : wxBaseEnumProperty(label,name)
1271
if ( &labels && labels.size() )
1273
m_choices.Set(labels, values);
1275
if ( GetItemCount() )
1276
SetValue( (long)value );
1280
wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name,
1281
wxPGChoices& choices, int value )
1282
: wxBaseEnumProperty(label,name)
1284
m_choices.Assign( choices );
1286
if ( GetItemCount() )
1287
SetValue( (long)value );
1290
int wxEnumProperty::GetIndexForValue( int value ) const
1292
if ( !m_choices.IsOk() )
1295
int intVal = m_choices.Index(value);
1302
wxEnumProperty::~wxEnumProperty ()
1306
const wxString* wxEnumProperty::GetEntry( size_t index, int* pvalue ) const
1308
if ( m_choices.IsOk() && index < m_choices.GetCount() )
1310
int value = m_choices.GetValue(index);
1315
return &m_choices.GetLabel(index);
1317
return (const wxString*) NULL;
1320
int wxEnumProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo )
1323
choiceinfo->m_choices = &m_choices;
1325
if ( !m_choices.IsOk() )
1331
// -----------------------------------------------------------------------
1332
// wxEditEnumProperty
1333
// -----------------------------------------------------------------------
1335
IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty, wxPGProperty)
1337
WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty,wxString,ComboBox)
1339
wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1340
const long* values, const wxString& value )
1341
: wxEnumProperty(label,name,labels,values,0)
1346
wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels,
1347
const long* values, wxPGChoices* choicesCache, const wxString& value )
1348
: wxEnumProperty(label,name,labels,values,choicesCache,0)
1353
wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name,
1354
const wxArrayString& labels, const wxArrayInt& values, const wxString& value )
1355
: wxEnumProperty(label,name,labels,values,0)
1360
wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name,
1361
wxPGChoices& choices, const wxString& value )
1362
: wxEnumProperty(label,name,choices,0)
1367
wxEditEnumProperty::~wxEditEnumProperty()
1371
// -----------------------------------------------------------------------
1373
// -----------------------------------------------------------------------
1375
IMPLEMENT_DYNAMIC_CLASS(wxFlagsProperty,wxPGProperty)
1377
WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty,long,TextCtrl)
1379
void wxFlagsProperty::Init()
1381
SetFlag(wxPG_PROP_AGGREGATE); // This is must be done here to support flag props
1382
// with inital zero children.
1384
long value = m_value;
1387
// Generate children
1391
unsigned int prevChildCount = m_children.GetCount();
1394
if ( prevChildCount )
1396
wxPropertyGridState* state = GetParentState();
1398
// State safety check (it may be NULL in immediate parent)
1403
wxPGProperty* selected = state->GetSelection();
1406
if ( selected->GetParent() == this )
1407
oldSel = selected->GetArrIndex();
1408
else if ( selected == this )
1412
state->DoClearSelection();
1415
// Delete old children
1416
for ( i=0; i<prevChildCount; i++ )
1417
delete ( (wxPGProperty*) m_children[i] );
1421
if ( m_choices.IsOk() )
1423
const wxPGChoices& choices = m_choices;
1425
for ( i=0; i<GetItemCount(); i++ )
1427
bool child_val = ( value & choices.GetValue(i) )?true:false;
1429
wxPGProperty* boolProp;
1432
if ( wxPGGlobalVars->m_autoGetTranslation )
1434
boolProp = new wxBoolProperty( ::wxGetTranslation( GetLabel(i) ), wxPG_LABEL, child_val );
1439
boolProp = new wxBoolProperty( GetLabel(i), wxPG_LABEL, child_val );
1441
AddPrivateChild(boolProp);
1444
m_oldChoicesData = m_choices.GetDataPtr();
1447
m_oldValue = m_value;
1449
if ( prevChildCount )
1450
SubPropsChanged(oldSel);
1453
wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name,
1454
const wxChar** labels, const long* values, long value ) : wxPGProperty(label,name)
1456
m_oldChoicesData = (wxPGChoicesData*) NULL;
1460
m_choices.Set(labels,values);
1462
wxASSERT( GetItemCount() );
1468
m_value = wxPGVariant_Zero;
1472
wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name,
1473
const wxArrayString& labels, const wxArrayInt& values, int value )
1474
: wxPGProperty(label,name)
1476
m_oldChoicesData = (wxPGChoicesData*) NULL;
1478
if ( &labels && labels.size() )
1480
m_choices.Set(labels,values);
1482
wxASSERT( GetItemCount() );
1484
SetValue( (long)value );
1488
m_value = wxPGVariant_Zero;
1492
wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name,
1493
wxPGChoices& choices, long value )
1494
: wxPGProperty(label,name)
1496
m_oldChoicesData = (wxPGChoicesData*) NULL;
1498
if ( choices.IsOk() )
1500
m_choices.Assign(choices);
1502
wxASSERT( GetItemCount() );
1508
m_value = wxPGVariant_Zero;
1512
wxFlagsProperty::~wxFlagsProperty()
1516
void wxFlagsProperty::OnSetValue()
1518
if ( !m_choices.IsOk() || !GetItemCount() )
1520
m_value = wxPGVariant_Zero;
1524
long val = m_value.GetLong();
1528
// normalize the value (i.e. remove extra flags)
1530
const wxPGChoices& choices = m_choices;
1531
for ( i = 0; i < GetItemCount(); i++ )
1533
fullFlags |= choices.GetValue(i);
1540
// Need to (re)init now?
1541
if ( GetCount() != GetItemCount() ||
1542
m_choices.GetDataPtr() != m_oldChoicesData )
1548
long newFlags = m_value;
1550
if ( newFlags != m_oldValue )
1552
// Set child modified states
1554
const wxPGChoices& choices = m_choices;
1555
for ( i = 0; i<GetItemCount(); i++ )
1559
flag = choices.GetValue(i);
1561
if ( (newFlags & flag) != (m_oldValue & flag) )
1562
Item(i)->SetFlag( wxPG_PROP_MODIFIED );
1565
m_oldValue = newFlags;
1569
wxString wxFlagsProperty::GetValueAsString( int ) const
1573
if ( !m_choices.IsOk() )
1576
long flags = m_value;
1578
const wxPGChoices& choices = m_choices;
1580
for ( i = 0; i < GetItemCount(); i++ )
1583
doAdd = ( flags & choices.GetValue(i) );
1587
text += choices.GetLabel(i);
1592
// remove last comma
1593
if ( text.Len() > 1 )
1594
text.Truncate ( text.Len() - 2 );
1599
// Translate string into flag tokens
1600
bool wxFlagsProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
1602
if ( !m_choices.IsOk() )
1607
// semicolons are no longer valid delimeters
1608
WX_PG_TOKENIZER1_BEGIN(text,wxT(','))
1610
if ( token.length() )
1612
// Determine which one it is
1613
long bit = IdToBit( token );
1626
WX_PG_TOKENIZER1_END()
1630
if ( m_value.IsNull() || newFlags != m_value.GetLong() )
1636
// Converts string id to a relevant bit.
1637
long wxFlagsProperty::IdToBit( const wxString& id ) const
1640
for ( i = 0; i < GetItemCount(); i++ )
1642
if ( id == GetLabel(i) )
1644
return m_choices.GetValue(i);
1650
void wxFlagsProperty::RefreshChildren()
1652
if ( !m_choices.IsOk() || !GetCount() ) return;
1654
int flags = m_value.GetLong();
1656
const wxPGChoices& choices = m_choices;
1658
for ( i = 0; i < GetItemCount(); i++ )
1662
flag = choices.GetValue(i);
1664
long subVal = flags & flag;
1665
wxPGProperty* p = Item(i);
1667
if ( subVal != (m_oldValue & flag) )
1668
p->SetFlag( wxPG_PROP_MODIFIED );
1670
p->SetValue( subVal?true:false );
1676
void wxFlagsProperty::ChildChanged( wxVariant& thisValue, int childIndex, wxVariant& childValue ) const
1678
long oldValue = thisValue.GetLong();
1679
long val = childValue.GetLong();
1680
unsigned long vi = m_choices.GetValue(childIndex);
1682
thisValue = (long)(oldValue | vi);
1684
thisValue = (long)(oldValue & ~(vi));
1687
int wxFlagsProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo )
1690
choiceinfo->m_choices = &m_choices;
1694
// -----------------------------------------------------------------------
1696
// -----------------------------------------------------------------------
1698
WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxDirProperty,wxLongStringProperty,const wxString&)
1700
wxDirProperty::wxDirProperty( const wxString& name, const wxString& label, const wxString& value )
1701
: wxLongStringProperty(name,label,value)
1703
m_flags |= wxPG_NO_ESCAPE;
1705
wxDirProperty::~wxDirProperty() { }
1707
wxValidator* wxDirProperty::DoGetValidator() const
1709
return wxFileProperty::GetClassValidator();
1712
bool wxDirProperty::OnButtonClick( wxPropertyGrid* propGrid, wxString& value )
1714
wxSize dlg_sz(300,400);
1716
wxDirDialog dlg( propGrid,
1717
m_dlgMessage.length() ? m_dlgMessage : wxString(_("Choose a directory:")),
1720
#if !wxPG_SMALL_SCREEN
1721
propGrid->GetGoodEditorDialogPosition(this,dlg_sz),
1728
if ( dlg.ShowModal() == wxID_OK )
1730
value = dlg.GetPath();
1736
bool wxDirProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1738
if ( name == wxPG_DIR_DIALOG_MESSAGE )
1740
m_dlgMessage = value.GetString();
1746
// -----------------------------------------------------------------------
1747
// wxPGFileDialogAdapter
1748
// -----------------------------------------------------------------------
1750
bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property )
1752
wxFileProperty* fileProp = NULL;
1756
if ( property->IsKindOf(CLASSINFO(wxFileProperty)) )
1758
fileProp = ((wxFileProperty*)property);
1759
path = fileProp->m_filename.GetPath();
1760
indFilter = fileProp->m_indFilter;
1762
if ( !path.length() && fileProp->m_basePath.length() )
1763
path = fileProp->m_basePath;
1767
wxFileName fn(property->GetValue().GetString());
1768
path = fn.GetPath();
1771
wxFileDialog dlg( propGrid->GetPanel(),
1772
property->GetAttribute(wxT("DialogTitle"), _("Choose a file")),
1773
property->GetAttribute(wxT("InitialPath"), path),
1775
property->GetAttribute(wxPG_FILE_WILDCARD, _("All files (*.*)|*.*")),
1777
wxDefaultPosition );
1779
if ( indFilter >= 0 )
1780
dlg.SetFilterIndex( indFilter );
1782
if ( dlg.ShowModal() == wxID_OK )
1785
fileProp->m_indFilter = dlg.GetFilterIndex();
1786
SetValue( dlg.GetPath() );
1792
// -----------------------------------------------------------------------
1794
// -----------------------------------------------------------------------
1796
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty,wxPGProperty,
1797
wxString,const wxString&,TextCtrlAndButton)
1799
wxFileProperty::wxFileProperty( const wxString& label, const wxString& name,
1800
const wxString& value ) : wxPGProperty(label,name)
1802
m_flags |= wxPG_PROP_SHOW_FULL_FILENAME;
1804
SetAttribute( wxPG_FILE_WILDCARD, _("All files (*.*)|*.*") );
1809
wxFileProperty::~wxFileProperty() {}
1811
#if wxUSE_VALIDATORS
1813
wxValidator* wxFileProperty::GetClassValidator()
1815
WX_PG_DOGETVALIDATOR_ENTRY()
1817
// Atleast wxPython 2.6.2.1 required that the string argument is given
1819
wxTextValidator* validator = new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST,&v);
1821
wxArrayString exChars;
1822
exChars.Add(wxT("?"));
1823
exChars.Add(wxT("*"));
1824
exChars.Add(wxT("|"));
1825
exChars.Add(wxT("<"));
1826
exChars.Add(wxT(">"));
1827
exChars.Add(wxT("\""));
1829
validator->SetExcludes(exChars);
1831
WX_PG_DOGETVALIDATOR_EXIT(validator)
1834
wxValidator* wxFileProperty::DoGetValidator() const
1836
return GetClassValidator();
1841
void wxFileProperty::OnSetValue()
1843
const wxString& fnstr = m_value.GetString();
1847
if ( !m_filename.HasName() )
1849
m_value = wxPGVariant_EmptyString;
1853
// Find index for extension.
1854
if ( m_indFilter < 0 && fnstr.length() )
1856
wxString ext = m_filename.GetExt();
1859
size_t len = m_wildcard.length();
1861
pos = m_wildcard.find(wxT("|"), pos);
1862
while ( pos != wxString::npos && pos < (len-3) )
1864
size_t ext_begin = pos + 3;
1866
pos = m_wildcard.find(wxT("|"), ext_begin);
1867
if ( pos == wxString::npos )
1869
wxString found_ext = m_wildcard.substr(ext_begin, pos-ext_begin);
1871
if ( found_ext.length() > 0 )
1873
if ( found_ext[0] == wxT('*') )
1875
m_indFilter = curind;
1878
if ( ext.CmpNoCase(found_ext) == 0 )
1880
m_indFilter = curind;
1886
pos = m_wildcard.find(wxT("|"), pos+1);
1893
wxString wxFileProperty::GetValueAsString( int argFlags ) const
1895
// Always return empty string when name component is empty
1896
wxString fullName = m_filename.GetFullName();
1897
if ( !fullName.length() )
1900
if ( argFlags & wxPG_FULL_VALUE )
1902
return m_filename.GetFullPath();
1904
else if ( m_flags & wxPG_PROP_SHOW_FULL_FILENAME )
1906
if ( m_basePath.Length() )
1908
wxFileName fn2(m_filename);
1909
fn2.MakeRelativeTo(m_basePath);
1910
return fn2.GetFullPath();
1912
return m_filename.GetFullPath();
1915
return m_filename.GetFullName();
1918
wxPGEditorDialogAdapter* wxFileProperty::GetEditorDialog() const
1920
return new wxPGFileDialogAdapter();
1923
bool wxFileProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const
1925
if ( (m_flags & wxPG_PROP_SHOW_FULL_FILENAME) || (argFlags & wxPG_FULL_VALUE) )
1927
if ( m_filename != text )
1935
if ( m_filename.GetFullName() != text )
1937
wxFileName fn = m_filename;
1938
fn.SetFullName(text);
1939
variant = fn.GetFullPath();
1947
bool wxFileProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1949
// Return false on some occasions to make sure those attribs will get
1950
// stored in m_attributes.
1951
if ( name == wxPG_FILE_SHOW_FULL_PATH )
1953
if ( wxPGVariantToInt(value) )
1954
m_flags |= wxPG_PROP_SHOW_FULL_FILENAME;
1956
m_flags &= ~(wxPG_PROP_SHOW_FULL_FILENAME);
1959
else if ( name == wxPG_FILE_WILDCARD )
1961
m_wildcard = value.GetString();
1963
else if ( name == wxPG_FILE_SHOW_RELATIVE_PATH )
1965
m_basePath = value.GetString();
1967
// Make sure wxPG_FILE_SHOW_FULL_PATH is also set
1968
m_flags |= wxPG_PROP_SHOW_FULL_FILENAME;
1970
else if ( name == wxPG_FILE_INITIAL_PATH )
1972
m_initialPath = value.GetString();
1975
else if ( name == wxPG_FILE_DIALOG_TITLE )
1977
m_dlgTitle = value.GetString();
1983
// -----------------------------------------------------------------------
1984
// wxPGLongStringDialogAdapter
1985
// -----------------------------------------------------------------------
1987
bool wxPGLongStringDialogAdapter::DoShowDialog( wxPropertyGrid* propGrid, wxPGProperty* property )
1989
wxString val1 = property->GetValueAsString(0);
1990
wxString val_orig = val1;
1993
if ( !property->HasFlag(wxPG_PROP_NO_ESCAPE) )
1994
wxPropertyGrid::ExpandEscapeSequences(value, val1);
1996
value = wxString(val1);
1998
// Run editor dialog.
1999
if ( wxLongStringProperty::DisplayEditorDialog(property, propGrid, value) )
2001
if ( !property->HasFlag(wxPG_PROP_NO_ESCAPE) )
2002
wxPropertyGrid::CreateEscapeSequences(val1,value);
2006
if ( val1 != val_orig )
2015
// -----------------------------------------------------------------------
2016
// wxLongStringProperty
2017
// -----------------------------------------------------------------------
2019
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty,wxPGProperty,
2020
wxString,const wxString&,TextCtrlAndButton)
2022
wxLongStringProperty::wxLongStringProperty( const wxString& label, const wxString& name,
2023
const wxString& value ) : wxPGProperty(label,name)
2028
wxLongStringProperty::~wxLongStringProperty() {}
2030
wxString wxLongStringProperty::GetValueAsString( int ) const
2035
bool wxLongStringProperty::OnEvent( wxPropertyGrid* propGrid, wxWindow* WXUNUSED(primary),
2038
if ( propGrid->IsMainButtonEvent(event) )
2041
PrepareValueForDialogEditing(propGrid);
2043
wxString val1 = GetValueAsString(0);
2044
wxString val_orig = val1;
2047
if ( !(m_flags & wxPG_PROP_NO_ESCAPE) )
2048
wxPropertyGrid::ExpandEscapeSequences(value,val1);
2050
value = wxString(val1);
2052
// Run editor dialog.
2053
if ( OnButtonClick(propGrid,value) )
2055
if ( !(m_flags & wxPG_PROP_NO_ESCAPE) )
2056
wxPropertyGrid::CreateEscapeSequences(val1,value);
2060
if ( val1 != val_orig )
2062
SetValueInEvent( val1 );
2070
bool wxLongStringProperty::OnButtonClick( wxPropertyGrid* propGrid, wxString& value )
2072
return DisplayEditorDialog(this, propGrid, value);
2075
bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty* prop, wxPropertyGrid* propGrid, wxString& value )
2078
// launch editor dialog
2079
wxDialog* dlg = new wxDialog(propGrid,-1,prop->GetLabel(),wxDefaultPosition,wxDefaultSize,
2080
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxCLIP_CHILDREN);
2082
dlg->SetFont(propGrid->GetFont()); // To allow entering chars of the same set as the propGrid
2084
// Multi-line text editor dialog.
2085
#if !wxPG_SMALL_SCREEN
2086
const int spacing = 8;
2088
const int spacing = 4;
2090
wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL );
2091
wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL );
2092
wxTextCtrl* ed = new wxTextCtrl(dlg,11,value,
2093
wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE);
2095
rowsizer->Add( ed, 1, wxEXPAND|wxALL, spacing );
2096
topsizer->Add( rowsizer, 1, wxEXPAND, 0 );
2098
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
2099
buttonSizer->AddButton(new wxButton(dlg, wxID_OK));
2100
buttonSizer->AddButton(new wxButton(dlg, wxID_CANCEL));
2101
buttonSizer->Realize();
2102
topsizer->Add( buttonSizer, 0,
2103
wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxRIGHT,
2106
dlg->SetSizer( topsizer );
2107
topsizer->SetSizeHints( dlg );
2109
#if !wxPG_SMALL_SCREEN
2110
dlg->SetSize(400,300);
2112
dlg->Move( propGrid->GetGoodEditorDialogPosition(prop,dlg->GetSize()) );
2115
int res = dlg->ShowModal();
2117
if ( res == wxID_OK )
2119
value = ed->GetValue();
2127
bool wxLongStringProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2129
if ( m_value.IsNull() || m_value != text )
2137
// -----------------------------------------------------------------------
2138
// wxArrayEditorDialog
2139
// -----------------------------------------------------------------------
2141
BEGIN_EVENT_TABLE(wxArrayEditorDialog, wxDialog)
2142
EVT_IDLE(wxArrayEditorDialog::OnIdle)
2143
EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick)
2144
EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick)
2145
EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick)
2146
EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick)
2147
EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick)
2148
EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick)
2149
EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick)
2150
//EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick)
2153
IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog, wxDialog)
2155
#include <wx/statline.h>
2157
// -----------------------------------------------------------------------
2159
void wxArrayEditorDialog::OnIdle(wxIdleEvent& event)
2162
// Do control focus detection here.
2165
wxWindow* focused = FindFocus();
2167
// This strange focus thing is a workaround for wxGTK wxListBox focus
2169
if ( m_curFocus == 0 && focused != m_edValue &&
2170
focused != m_butAdd && focused != m_butUpdate &&
2171
m_lbStrings->GetSelection() >= 0 )
2173
// ListBox was just focused.
2174
m_butAdd->Enable(false);
2175
m_butUpdate->Enable(false);
2176
m_butRemove->Enable(true);
2177
m_butUp->Enable(true);
2178
m_butDown->Enable(true);
2181
else if ( (m_curFocus == 1 && focused == m_edValue) /*|| m_curFocus == 2*/ )
2183
// TextCtrl was just focused.
2184
m_butAdd->Enable(true);
2185
bool upd_enable = false;
2186
if ( m_lbStrings->GetCount() && m_lbStrings->GetSelection() >= 0 )
2188
m_butUpdate->Enable(upd_enable);
2189
m_butRemove->Enable(false);
2190
m_butUp->Enable(false);
2191
m_butDown->Enable(false);
2198
// -----------------------------------------------------------------------
2200
wxArrayEditorDialog::wxArrayEditorDialog()
2206
// -----------------------------------------------------------------------
2208
void wxArrayEditorDialog::Init()
2210
m_custBtText = (const wxChar*) NULL;
2211
#if defined(__WXPYTHON__)
2212
m_scriptObject = NULL;
2216
// -----------------------------------------------------------------------
2218
wxArrayEditorDialog::wxArrayEditorDialog( wxWindow *parent,
2219
const wxString& message,
2220
const wxString& caption,
2227
Create(parent,message,caption,style,pos,sz);
2230
// -----------------------------------------------------------------------
2232
bool wxArrayEditorDialog::Create( wxWindow *parent,
2233
const wxString& message,
2234
const wxString& caption,
2239
// On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION
2240
// FIXME: This should be only a temporary fix.
2242
int useStyle = wxCAPTION;
2244
int useStyle = style;
2247
bool res = wxDialog::Create(parent, wxID_ANY, caption, pos, sz, useStyle);
2249
SetFont(parent->GetFont()); // To allow entering chars of the same set as the propGrid
2251
#if !wxPG_SMALL_SCREEN
2252
const int spacing = 4;
2254
const int spacing = 3;
2261
wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL );
2264
if ( message.length() )
2265
topsizer->Add( new wxStaticText(this,-1,message),
2266
0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing );
2269
wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL );
2270
m_edValue = new wxTextCtrl(this,21,wxEmptyString,
2271
wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
2272
wxValidator* validator = GetTextCtrlValidator();
2275
m_edValue->SetValidator( *validator );
2278
rowsizer->Add( m_edValue,
2279
1, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing );
2282
m_butAdd = new wxButton(this,22,_("Add"));
2283
rowsizer->Add( m_butAdd,
2284
0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, spacing );
2285
topsizer->Add( rowsizer, 0, wxEXPAND, spacing );
2288
topsizer->Add( new wxStaticLine(this,-1),
2289
0, wxEXPAND|wxBOTTOM|wxLEFT|wxRIGHT, spacing );
2291
rowsizer = new wxBoxSizer( wxHORIZONTAL );
2294
m_lbStrings = new wxListBox(this, 24, wxDefaultPosition, wxDefaultSize);
2296
for ( i=0; i<ArrayGetCount(); i++ )
2297
m_lbStrings->Append( ArrayGet(i) );
2298
rowsizer->Add( m_lbStrings, 1, wxEXPAND|wxRIGHT, spacing );
2300
// Manipulator buttons
2301
wxBoxSizer* colsizer = new wxBoxSizer( wxVERTICAL );
2302
m_butCustom = (wxButton*) NULL;
2305
m_butCustom = new wxButton(this,28,::wxGetTranslation(m_custBtText));
2306
colsizer->Add( m_butCustom,
2307
0, wxALIGN_CENTER|wxTOP/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/,
2310
m_butUpdate = new wxButton(this,27,_("Update"));
2311
colsizer->Add( m_butUpdate,
2312
0, wxALIGN_CENTER|wxTOP, spacing );
2313
m_butRemove = new wxButton(this,23,_("Remove"));
2314
colsizer->Add( m_butRemove,
2315
0, wxALIGN_CENTER|wxTOP, spacing );
2316
m_butUp = new wxButton(this,25,_("Up"));
2317
colsizer->Add( m_butUp,
2318
0, wxALIGN_CENTER|wxTOP, spacing );
2319
m_butDown = new wxButton(this,26,_("Down"));
2320
colsizer->Add( m_butDown,
2321
0, wxALIGN_CENTER|wxTOP, spacing );
2322
rowsizer->Add( colsizer, 0, 0, spacing );
2324
topsizer->Add( rowsizer, 1, wxLEFT|wxRIGHT|wxEXPAND, spacing );
2327
topsizer->Add( new wxStaticLine(this,-1),
2328
0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, spacing );
2330
// Standard dialog buttons
2331
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
2332
buttonSizer->AddButton(new wxButton(this, wxID_OK));
2333
buttonSizer->AddButton(new wxButton(this, wxID_CANCEL));
2334
buttonSizer->Realize();
2335
topsizer->Add( buttonSizer, 0,
2336
wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxALL,
2339
m_edValue->SetFocus();
2341
SetSizer( topsizer );
2342
topsizer->SetSizeHints( this );
2344
#if !wxPG_SMALL_SCREEN
2345
if ( sz.x == wxDefaultSize.x &&
2346
sz.y == wxDefaultSize.y )
2347
SetSize( wxSize(275,360) );
2355
// -----------------------------------------------------------------------
2357
void wxArrayEditorDialog::OnAddClick(wxCommandEvent& )
2359
wxString text = m_edValue->GetValue();
2360
if ( text.length() )
2362
if ( ArrayInsert( text, -1 ) )
2364
m_lbStrings->Append( text );
2371
// -----------------------------------------------------------------------
2373
void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent& )
2375
int index = m_lbStrings->GetSelection();
2378
ArrayRemoveAt( index );
2379
m_lbStrings->Delete ( index );
2384
// -----------------------------------------------------------------------
2386
void wxArrayEditorDialog::OnUpClick(wxCommandEvent& )
2388
int index = m_lbStrings->GetSelection();
2391
ArraySwap(index-1,index);
2392
/*wxString old_str = m_array[index-1];
2393
wxString new_str = m_array[index];
2394
m_array[index-1] = new_str;
2395
m_array[index] = old_str;*/
2396
m_lbStrings->SetString ( index-1, ArrayGet(index-1) );
2397
m_lbStrings->SetString ( index, ArrayGet(index) );
2398
m_lbStrings->SetSelection ( index-1 );
2403
// -----------------------------------------------------------------------
2405
void wxArrayEditorDialog::OnDownClick(wxCommandEvent& )
2407
int index = m_lbStrings->GetSelection();
2408
int lastStringIndex = ((int) m_lbStrings->GetCount()) - 1;
2409
if ( index >= 0 && index < lastStringIndex )
2411
ArraySwap(index,index+1);
2412
/*wxString old_str = m_array[index+1];
2413
wxString new_str = m_array[index];
2414
m_array[index+1] = new_str;
2415
m_array[index] = old_str;*/
2416
m_lbStrings->SetString ( index+1, ArrayGet(index+1) );
2417
m_lbStrings->SetString ( index, ArrayGet(index) );
2418
m_lbStrings->SetSelection ( index+1 );
2423
// -----------------------------------------------------------------------
2425
void wxArrayEditorDialog::OnUpdateClick(wxCommandEvent& )
2427
int index = m_lbStrings->GetSelection();
2430
wxString str = m_edValue->GetValue();
2431
if ( ArraySet(index,str) )
2433
m_lbStrings->SetString ( index, str );
2434
//m_array[index] = str;
2440
// -----------------------------------------------------------------------
2442
void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent& )
2444
int index = m_lbStrings->GetSelection();
2447
m_edValue->SetValue( m_lbStrings->GetString(index) );
2451
// -----------------------------------------------------------------------
2452
// wxPGArrayStringEditorDialog
2453
// -----------------------------------------------------------------------
2455
IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog, wxArrayEditorDialog)
2457
BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog, wxArrayEditorDialog)
2458
EVT_BUTTON(28, wxPGArrayStringEditorDialog::OnCustomEditClick)
2461
// -----------------------------------------------------------------------
2463
wxString wxPGArrayStringEditorDialog::ArrayGet( size_t index )
2465
return m_array[index];
2468
size_t wxPGArrayStringEditorDialog::ArrayGetCount()
2470
return m_array.GetCount();
2473
bool wxPGArrayStringEditorDialog::ArrayInsert( const wxString& str, int index )
2478
m_array.Insert(str,index);
2482
bool wxPGArrayStringEditorDialog::ArraySet( size_t index, const wxString& str )
2484
m_array[index] = str;
2488
void wxPGArrayStringEditorDialog::ArrayRemoveAt( int index )
2490
m_array.RemoveAt(index);
2493
void wxPGArrayStringEditorDialog::ArraySwap( size_t first, size_t second )
2495
wxString old_str = m_array[first];
2496
wxString new_str = m_array[second];
2497
m_array[first] = new_str;
2498
m_array[second] = old_str;
2501
wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog()
2502
: wxArrayEditorDialog()
2507
void wxPGArrayStringEditorDialog::Init()
2509
m_pCallingClass = (wxArrayStringProperty*) NULL;
2512
void wxPGArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent& )
2514
wxASSERT( m_pCallingClass );
2515
wxString str = m_edValue->GetValue();
2516
if ( m_pCallingClass->OnCustomStringEdit(m_parent,str) )
2518
//m_edValue->SetValue ( str );
2519
m_lbStrings->Append ( str );
2520
m_array.Add ( str );
2525
// -----------------------------------------------------------------------
2526
// wxArrayStringProperty
2527
// -----------------------------------------------------------------------
2529
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty, // Property name
2530
wxPGProperty, // Property we inherit from
2531
wxArrayString, // Value type name
2532
const wxArrayString&, // Value type, as given in constructor
2533
TextCtrlAndButton) // Initial editor
2535
wxArrayStringProperty::wxArrayStringProperty( const wxString& label,
2536
const wxString& name,
2537
const wxArrayString& array )
2538
: wxPGProperty(label,name)
2543
wxArrayStringProperty::~wxArrayStringProperty() { }
2545
void wxArrayStringProperty::OnSetValue()
2547
GenerateValueAsString();
2550
wxString wxArrayStringProperty::GetValueAsString( int WXUNUSED(argFlags) ) const
2555
// Converts wxArrayString to a string separated by delimeters and spaces.
2556
// preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash
2558
void wxPropertyGrid::ArrayStringToString( wxString& dst, const wxArrayString& src,
2559
wxChar preDelim, wxChar postDelim,
2565
unsigned int itemCount = src.GetCount();
2573
else if ( (flags & 1) )
2575
preas[0] = preDelim;
2582
dst.append( preas );
2584
wxASSERT( postDelim );
2585
wxString postDelimStr(postDelim);
2586
//wxString preDelimStr(preDelim);
2588
for ( i = 0; i < itemCount; i++ )
2590
wxString str( src.Item(i) );
2592
// Do some character conversion.
2593
// Convertes \ to \\ and <preDelim> to \<preDelim>
2594
// Useful when preDelim and postDelim are "\"".
2597
str.Replace( wxT("\\"), wxT("\\\\"), true );
2599
str.Replace( preas, pdr, true );
2604
if ( i < (itemCount-1) )
2606
dst.append( postDelimStr );
2607
dst.append( wxT(" ") );
2608
dst.append( preas );
2610
else if ( preDelim )
2611
dst.append( postDelimStr );
2615
#define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \
2616
wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxT('"'),wxT('"'),1);
2618
void wxArrayStringProperty::GenerateValueAsString()
2620
wxArrayString arr = m_value.GetArrayString();
2621
ARRSTRPROP_ARRAY_TO_STRING(m_display, arr)
2624
// Default implementation doesn't do anything.
2625
bool wxArrayStringProperty::OnCustomStringEdit( wxWindow*, wxString& )
2630
wxArrayEditorDialog* wxArrayStringProperty::CreateEditorDialog()
2632
return new wxPGArrayStringEditorDialog();
2635
bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid* propGrid,
2636
wxWindow* WXUNUSED(primaryCtrl),
2640
PrepareValueForDialogEditing(propGrid);
2642
if ( !propGrid->EditorValidate() )
2645
// Create editor dialog.
2646
wxArrayEditorDialog* dlg = CreateEditorDialog();
2647
#if wxUSE_VALIDATORS
2648
wxValidator* validator = GetValidator();
2649
wxPGInDialogValidator dialogValidator;
2652
wxPGArrayStringEditorDialog* strEdDlg = wxDynamicCast(dlg, wxPGArrayStringEditorDialog);
2655
strEdDlg->SetCustomButton(cbt, this);
2657
dlg->SetDialogValue( wxVariant(m_value) );
2658
dlg->Create(propGrid, wxEmptyString, m_label);
2660
#if !wxPG_SMALL_SCREEN
2661
dlg->Move( propGrid->GetGoodEditorDialogPosition(this,dlg->GetSize()) );
2670
int res = dlg->ShowModal();
2672
if ( res == wxID_OK && dlg->IsModified() )
2674
wxVariant value = dlg->GetDialogValue();
2675
if ( !value.IsNull() )
2677
wxArrayString actualValue = value.GetArrayString();
2679
ARRSTRPROP_ARRAY_TO_STRING(tempStr, actualValue)
2680
#if wxUSE_VALIDATORS
2681
if ( dialogValidator.DoValidate( propGrid, validator, tempStr ) )
2684
SetValueInEvent( actualValue );
2701
bool wxArrayStringProperty::OnEvent( wxPropertyGrid* propGrid,
2705
if ( propGrid->IsMainButtonEvent(event) )
2706
return OnButtonClick(propGrid,primary,(const wxChar*) NULL);
2710
bool wxArrayStringProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2714
WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
2716
// Need to replace backslashes with empty characters
2717
// (opposite what is done in GenerateValueString).
2718
token.Replace ( wxT("\\\\"), wxT("\\"), true );
2722
WX_PG_TOKENIZER2_END()
2729
// -----------------------------------------------------------------------
2731
// -----------------------------------------------------------------------
2733
IMPLEMENT_DYNAMIC_CLASS(wxCustomProperty, wxPGProperty)
2735
const wxPGEditor* wxCustomProperty::DoGetEditorClass() const
2737
return wxPG_EDITOR(TextCtrl);
2740
wxCustomProperty::wxCustomProperty( const wxString& label,
2741
const wxString& name )
2742
: wxPGProperty(label,name)
2744
#ifdef wxPG_COMPATIBILITY_1_0_0
2745
m_callback = (wxPropertyGridCallback) NULL;
2747
m_paintCallback = (wxPGPaintCallback) NULL;
2748
m_value = wxPGVariant_EmptyString; // Do this to avoid having 'unspecified' value
2751
wxCustomProperty::~wxCustomProperty()
2755
bool wxCustomProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const
2757
if ( text != m_value.GetString() )
2765
wxString wxCustomProperty::GetValueAsString( int /*argFlags*/ ) const
2770
// Need to do some extra event handling.
2771
#ifdef wxPG_COMPATIBILITY_1_0_0
2772
bool wxCustomProperty::OnEvent( wxPropertyGrid* propGrid, wxWindow* primary, wxEvent& event )
2774
if ( propGrid->IsMainButtonEvent(event) )
2777
return m_callback(propGrid,this,primary,0);
2784
wxSize wxCustomProperty::OnMeasureImage( int item ) const
2786
if ( m_paintCallback )
2787
return wxSize(-wxPG_CUSTOM_IMAGE_WIDTH,-wxPG_CUSTOM_IMAGE_WIDTH);
2789
return wxPGProperty::OnMeasureImage(item);
2792
void wxCustomProperty::OnCustomPaint( wxDC& dc,
2794
wxPGPaintData& paintData )
2796
if ( m_paintCallback )
2797
m_paintCallback(this,dc,rect,paintData);
2799
wxPGProperty::OnCustomPaint(dc,rect,paintData);
2802
bool wxCustomProperty::IntToValue( wxVariant& variant, int number, int ) const
2804
int index = m_choices.Index(number);
2808
const wxString& sAtIndex = m_choices.GetLabel(index);
2809
if ( sAtIndex != m_value.GetString() )
2818
int wxCustomProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo )
2821
choiceinfo->m_choices = &m_choices;
2823
if ( !m_choices.IsOk() )
2826
return m_choices.Index(m_value.GetString());
2829
bool wxCustomProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2831
#ifdef wxPG_COMPATIBILITY_1_0_0
2832
wxPropertyGrid* grid = GetGrid();
2833
if ( name == wxPG_CUSTOM_EDITOR )
2836
grid->SetPropertyEditor( this, (wxPGEditor*) value.GetVoidPtr() );
2838
SetEditor( (wxPGEditor*) value.GetVoidPtr() );
2841
else if ( name == wxPG_CUSTOM_IMAGE )
2843
wxBitmap* bmp = (wxBitmap*) value.GetWxObjectPtr();
2845
grid->SetPropertyImage(this,*bmp);
2847
SetValueImage(*bmp);
2850
else if ( name == wxPG_CUSTOM_CALLBACK )
2852
m_callback = (wxPropertyGridCallback) value.GetVoidPtr();
2857
if ( name == wxPG_CUSTOM_PAINT_CALLBACK )
2859
void* voidValue = value.GetVoidPtr();
2860
m_paintCallback = (wxPGPaintCallback) voidValue;
2862
m_flags |= wxPG_PROP_CUSTOMIMAGE;
2863
else if ( !GetValueImage() )
2864
m_flags &= ~(wxPG_PROP_CUSTOMIMAGE);
2868
if ( name == wxPG_CUSTOM_PRIVATE_CHILDREN )
2870
if ( wxPGVariantToInt(value) )
2872
SetFlag( wxPG_PROP_AGGREGATE );
2876
ClearFlag( wxPG_PROP_AGGREGATE );
2883
// -----------------------------------------------------------------------
2885
#if wxUSE_VALIDATORS
2886
bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* propGrid,
2887
wxValidator* validator,
2888
const wxString& value )
2893
wxTextCtrl* tc = m_textCtrl;
2898
tc = new wxTextCtrl( propGrid, wxPG_SUBID_TEMP1, wxEmptyString,
2899
wxPoint(30000,30000));
2906
tc->SetValue(value);
2908
validator->SetWindow(tc);
2909
bool res = validator->Validate(propGrid);
2914
bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* WXUNUSED(propGrid),
2915
wxValidator* WXUNUSED(validator),
2916
const wxString& WXUNUSED(value) )
2922
// -----------------------------------------------------------------------