X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1c4293cb91327247ad69e6ec8d589bfaa299db28..bbd55ff9564dcaf1a5d2ee93d789c4d656baabef:/src/propgrid/props.cpp diff --git a/src/propgrid/props.cpp b/src/propgrid/props.cpp index e01c940bcc..755a79f1a3 100644 --- a/src/propgrid/props.cpp +++ b/src/propgrid/props.cpp @@ -4,9 +4,9 @@ // Author: Jaakko Salli // Modified by: // Created: 2005-05-14 -// RCS-ID: $Id: +// RCS-ID: $Id$ // Copyright: (c) Jaakko Salli -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". @@ -16,6 +16,8 @@ #pragma hdrstop #endif +#if wxUSE_PROPGRID + #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/object.h" @@ -29,6 +31,7 @@ #include "wx/dcclient.h" #include "wx/dcmemory.h" #include "wx/button.h" + #include "wx/bmpbuttn.h" #include "wx/pen.h" #include "wx/brush.h" #include "wx/cursor.h" @@ -44,13 +47,12 @@ #include "wx/sizer.h" #include "wx/textdlg.h" #include "wx/filedlg.h" - #include "wx/statusbr.h" #include "wx/intl.h" #endif -#include +#include "wx/filename.h" -#include +#include "wx/propgrid/propgrid.h" #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc. @@ -78,22 +80,30 @@ void wxStringProperty::OnSetValue() if ( HasFlag(wxPG_PROP_COMPOSED_VALUE) ) { wxString s; - GenerateComposedValue(s, 0); + DoGenerateComposedValue(s); m_value = s; } } wxStringProperty::~wxStringProperty() { } -wxString wxStringProperty::GetValueAsString( int argFlags ) const +wxString wxStringProperty::ValueToString( wxVariant& value, + int argFlags ) const { - wxString s = m_value.GetString(); + wxString s = value.GetString(); if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE) ) { // Value stored in m_value is non-editable, non-full value if ( (argFlags & wxPG_FULL_VALUE) || (argFlags & wxPG_EDITABLE_VALUE) ) - GenerateComposedValue(s, argFlags); + { + // Calling this under incorrect conditions will fail + wxASSERT_MSG( argFlags & wxPG_VALUE_IS_CURRENT, + "Sorry, currently default wxPGProperty::ValueToString() " + "implementation only works if value is m_value." ); + + DoGenerateComposedValue(s, argFlags); + } return s; } @@ -111,7 +121,7 @@ bool wxStringProperty::StringToValue( wxVariant& variant, const wxString& text, if ( GetChildCount() && HasFlag(wxPG_PROP_COMPOSED_VALUE) ) return wxPGProperty::StringToValue(variant, text, argFlags); - if ( m_value.GetString() != text ) + if ( variant != text ) { variant = text; return true; @@ -125,7 +135,7 @@ bool wxStringProperty::DoSetAttribute( const wxString& name, wxVariant& value ) if ( name == wxPG_STRING_PASSWORD ) { m_flags &= ~(wxPG_PROP_PASSWORD); - if ( wxPGVariantToInt(value) ) m_flags |= wxPG_PROP_PASSWORD; + if ( value.GetLong() ) m_flags |= wxPG_PROP_PASSWORD; RecreateEditor(); return false; } @@ -148,21 +158,25 @@ wxIntProperty::wxIntProperty( const wxString& label, const wxString& name, wxIntProperty::wxIntProperty( const wxString& label, const wxString& name, const wxLongLong& value ) : wxPGProperty(label,name) { - SetValue(wxLongLongToVariant(value)); + SetValue(WXVARIANT(value)); } wxIntProperty::~wxIntProperty() { } -wxString wxIntProperty::GetValueAsString( int ) const +wxString wxIntProperty::ValueToString( wxVariant& value, + int WXUNUSED(argFlags) ) const { - if ( wxPGIsVariantType(m_value, long) ) - return wxString::Format(wxS("%li"),m_value.GetLong()); - - wxLongLong* ll = &wxLongLongFromVariant(m_value); - if ( ll ) - return ll->ToString(); + if ( value.GetType() == wxPG_VARIANT_TYPE_LONG ) + { + return wxString::Format(wxS("%li"),value.GetLong()); + } + else if ( value.GetType() == wxPG_VARIANT_TYPE_LONGLONG ) + { + wxLongLong ll = value.GetLongLong(); + return ll.ToString(); + } - return wxEmptyString; + return wxEmptyString; } bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const @@ -186,7 +200,7 @@ bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int int firstNonZeroPos = 0; - for ( ; i != iMax; i++ ) + for ( ; i != iMax; ++i ) { wxChar c = *i; if ( c != wxS('0') && c != wxS(' ') ) @@ -196,7 +210,8 @@ bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int wxString useText = text.substr(firstNonZeroPos, text.length() - firstNonZeroPos); - bool isPrevLong = wxPGIsVariantType(variant, long); + wxString variantType = variant.GetType(); + bool isPrevLong = variantType == wxPG_VARIANT_TYPE_LONG; wxLongLong_t value64 = 0; @@ -204,17 +219,26 @@ bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int ( value64 >= INT_MAX || value64 <= INT_MIN ) ) { - wxLongLong* _m_value64 = &wxLongLongFromVariant(m_value); - if ( isPrevLong || !_m_value64 || _m_value64->GetValue() != value64 ) + bool doChangeValue = isPrevLong; + + if ( !isPrevLong && variantType == wxPG_VARIANT_TYPE_LONGLONG ) + { + wxLongLong oldValue = variant.GetLongLong(); + if ( oldValue.GetValue() != value64 ) + doChangeValue = true; + } + + if ( doChangeValue ) { - variant = wxLongLongToVariant(value64); + wxLongLong ll(value64); + variant = ll; return true; } } if ( useText.ToLong( &value32, 0 ) ) { - if ( !isPrevLong || m_value.GetLong() != value32 ) + if ( !isPrevLong || variant != value32 ) { variant = value32; return true; @@ -229,7 +253,7 @@ bool wxIntProperty::StringToValue( wxVariant& variant, const wxString& text, int bool wxIntProperty::IntToValue( wxVariant& variant, int value, int WXUNUSED(argFlags) ) const { - if ( !wxPGIsVariantType(variant, long) || variant.GetLong() != value ) + if ( variant.GetType() != wxPG_VARIANT_TYPE_LONG || variant != (long)value ) { variant = (long)value; return true; @@ -237,11 +261,22 @@ bool wxIntProperty::IntToValue( wxVariant& variant, int value, int WXUNUSED(argF return false; } -bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& value, wxPGValidationInfo* pValidationInfo, int mode ) -{ - // Check for min/max - wxLongLong_t min = wxINT64_MIN; - wxLongLong_t max = wxINT64_MAX; +// +// Common validation code to be called in ValidateValue() +// implementations. +// +// Note that 'value' is reference on purpose, so we can write +// back to it when mode is wxPG_PROPERTY_VALIDATION_SATURATE. +// +template +bool NumericValidation( const wxPGProperty* property, + T& value, + wxPGValidationInfo* pValidationInfo, + int mode, + const wxString& strFmt ) +{ + T min = (T) wxINT64_MIN; + T max = (T) wxINT64_MAX; wxVariant variant; bool minOk = false; bool maxOk = false; @@ -249,14 +284,14 @@ bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& va variant = property->GetAttribute(wxPGGlobalVars->m_strMin); if ( !variant.IsNull() ) { - wxPGVariantToLongLong(variant, &min); + variant.Convert(&min); minOk = true; } variant = property->GetAttribute(wxPGGlobalVars->m_strMax); if ( !variant.IsNull() ) { - wxPGVariantToLongLong(variant, &max); + variant.Convert(&max); maxOk = true; } @@ -265,7 +300,20 @@ bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& va if ( value < min ) { if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE ) - pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %lld or higher"),min); + { + wxString msg; + wxString smin = wxString::Format(strFmt, min); + wxString smax = wxString::Format(strFmt, max); + if ( !maxOk ) + msg = wxString::Format( + _("Value must be %s or higher."), + smin.c_str()); + else + msg = wxString::Format( + _("Value must be between %s and %s."), + smin.c_str(), smax.c_str()); + pValidationInfo->SetFailureMessage(msg); + } else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE ) value = min; else @@ -279,7 +327,20 @@ bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& va if ( value > max ) { if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE ) - pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %lld or higher"),min); + { + wxString msg; + wxString smin = wxString::Format(strFmt, min); + wxString smax = wxString::Format(strFmt, max); + if ( !minOk ) + msg = wxString::Format( + _("Value must be %s or less."), + smax.c_str()); + else + msg = wxString::Format( + _("Value must be between %s and %s."), + smin.c_str(), smax.c_str()); + pValidationInfo->SetFailureMessage(msg); + } else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE ) value = max; else @@ -290,12 +351,24 @@ bool wxIntProperty::DoValidation( const wxPGProperty* property, wxLongLong_t& va return true; } -bool wxIntProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const +bool wxIntProperty::DoValidation( const wxPGProperty* property, + wxLongLong_t& value, + wxPGValidationInfo* pValidationInfo, + int mode ) { - wxLongLong_t ll; - if ( wxPGVariantToLongLong(value, &ll) ) - return DoValidation(this, ll, &validationInfo, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE); - return true; + return NumericValidation(property, + value, + pValidationInfo, + mode, + wxS("%lld")); +} + +bool wxIntProperty::ValidateValue( wxVariant& value, + wxPGValidationInfo& validationInfo ) const +{ + wxLongLong_t ll = value.GetLongLong().GetValue(); + return DoValidation(this, ll, &validationInfo, + wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE); } wxValidator* wxIntProperty::GetClassValidator() @@ -325,21 +398,21 @@ wxValidator* wxIntProperty::DoGetValidator() const #define wxPG_UINT_TEMPLATE_MAX 8 -static const wxChar* gs_uintTemplates32[wxPG_UINT_TEMPLATE_MAX] = { +static const wxChar* const gs_uintTemplates32[wxPG_UINT_TEMPLATE_MAX] = { wxT("%x"),wxT("0x%x"),wxT("$%x"), wxT("%X"),wxT("0x%X"),wxT("$%X"), wxT("%u"),wxT("%o") }; -static const wxChar* gs_uintTemplates64[wxPG_UINT_TEMPLATE_MAX] = { - wxT("%") wxLongLongFmtSpec wxT("x"), - wxT("0x%") wxLongLongFmtSpec wxT("x"), - wxT("$%") wxLongLongFmtSpec wxT("x"), - wxT("%") wxLongLongFmtSpec wxT("X"), - wxT("0x%") wxLongLongFmtSpec wxT("X"), - wxT("$%") wxLongLongFmtSpec wxT("X"), - wxT("%") wxLongLongFmtSpec wxT("u"), - wxT("%") wxLongLongFmtSpec wxT("o") +static const char* const gs_uintTemplates64[wxPG_UINT_TEMPLATE_MAX] = { + "%" wxLongLongFmtSpec "x", + "0x%" wxLongLongFmtSpec "x", + "$%" wxLongLongFmtSpec "x", + "%" wxLongLongFmtSpec "X", + "0x%" wxLongLongFmtSpec "X", + "$%" wxLongLongFmtSpec "X", + "%" wxLongLongFmtSpec "u", + "%" wxLongLongFmtSpec "o" }; WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty,wxPGProperty, @@ -363,27 +436,33 @@ wxUIntProperty::wxUIntProperty( const wxString& label, const wxString& name, const wxULongLong& value ) : wxPGProperty(label,name) { Init(); - SetValue(wxULongLongToVariant(value)); + SetValue(WXVARIANT(value)); } wxUIntProperty::~wxUIntProperty() { } -wxString wxUIntProperty::GetValueAsString( int ) const +wxString wxUIntProperty::ValueToString( wxVariant& value, + int WXUNUSED(argFlags) ) const { size_t index = m_base + m_prefix; if ( index >= wxPG_UINT_TEMPLATE_MAX ) index = wxPG_BASE_DEC; - if ( wxPGIsVariantType(m_value, long) ) - return wxString::Format(gs_uintTemplates32[index],(unsigned long)m_value.GetLong()); - else - return wxString::Format(gs_uintTemplates64[index],wxULongLongFromVariant(m_value).GetValue()); + if ( value.GetType() == wxPG_VARIANT_TYPE_LONG ) + { + return wxString::Format(gs_uintTemplates32[index], + (unsigned long)value.GetLong()); + } + + wxULongLong ull = value.GetULongLong(); + + return wxString::Format(gs_uintTemplates64[index], ull.GetValue()); } bool wxUIntProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const { - //long unsigned value32 = 0; - bool isPrevLong = wxPGIsVariantType(variant, long); + wxString variantType = variant.GetType(); + bool isPrevLong = variantType == wxPG_VARIANT_TYPE_LONG; if ( text.length() == 0 ) { @@ -402,17 +481,25 @@ bool wxUIntProperty::StringToValue( wxVariant& variant, const wxString& text, in { if ( value64 >= LONG_MAX ) { - wxULongLong* _m_value64 = &wxULongLongFromVariant(m_value); - if ( isPrevLong || !_m_value64 || _m_value64->GetValue() != value64 ) + bool doChangeValue = isPrevLong; + + if ( !isPrevLong && variantType == wxPG_VARIANT_TYPE_ULONGLONG ) { - variant = wxULongLongToVariant(value64); + wxULongLong oldValue = variant.GetULongLong(); + if ( oldValue.GetValue() != value64 ) + doChangeValue = true; + } + + if ( doChangeValue ) + { + variant = wxULongLong(value64); return true; } } else { unsigned long value32 = wxLongLong(value64).GetLo(); - if ( !isPrevLong || m_value.GetLong() != (long)value32 ) + if ( !isPrevLong || m_value != (long)value32 ) { variant = (long)value32; return true; @@ -425,7 +512,7 @@ bool wxUIntProperty::StringToValue( wxVariant& variant, const wxString& text, in bool wxUIntProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const { - if ( m_value != (long)number ) + if ( variant != (long)number ) { variant = (long)number; return true; @@ -433,46 +520,15 @@ bool wxUIntProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(ar return false; } -#ifdef ULLONG_MAX - #define wxUINT64_MAX ULLONG_MAX - #define wxUINT64_MIN wxULL(0) -#else - #define wxUINT64_MAX wxULL(0xFFFFFFFFFFFFFFFF) - #define wxUINT64_MIN wxULL(0) -#endif - bool wxUIntProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const { - // Check for min/max - wxULongLong_t ll; - if ( wxPGVariantToULongLong(value, &ll) ) - { - wxULongLong_t min = wxUINT64_MIN; - wxULongLong_t max = wxUINT64_MAX; - wxVariant variant; - - variant = GetAttribute(wxPGGlobalVars->m_strMin); - if ( !variant.IsNull() ) - { - wxPGVariantToULongLong(variant, &min); - if ( ll < min ) - { - validationInfo.m_failureMessage = wxString::Format(_("Value must be %llu or higher"),min); - return false; - } - } - variant = GetAttribute(wxPGGlobalVars->m_strMax); - if ( !variant.IsNull() ) - { - wxPGVariantToULongLong(variant, &max); - if ( ll > max ) - { - validationInfo.m_failureMessage = wxString::Format(_("Value must be %llu or less"),max); - return false; - } - } - } - return true; + wxULongLong_t uul = value.GetULongLong().GetValue(); + return + NumericValidation(this, + uul, + &validationInfo, + wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE, + wxS("%llu")); } bool wxUIntProperty::DoSetAttribute( const wxString& name, wxVariant& value ) @@ -557,7 +613,7 @@ void wxPropertyGrid::DoubleToString(wxString& target, wxString::const_iterator i = target.end() - 1; size_t new_len = target.length() - 1; - for ( ; i != target.begin(); i-- ) + for ( ; i != target.begin(); --i ) { if ( *i != wxS('0') ) break; @@ -573,16 +629,17 @@ void wxPropertyGrid::DoubleToString(wxString& target, } } -wxString wxFloatProperty::GetValueAsString( int argFlags ) const +wxString wxFloatProperty::ValueToString( wxVariant& value, + int argFlags ) const { wxString text; - if ( !m_value.IsNull() ) + if ( !value.IsNull() ) { wxPropertyGrid::DoubleToString(text, - m_value, + value, m_precision, !(argFlags & wxPG_FULL_VALUE), - (wxString*) NULL); + NULL); } return text; } @@ -601,7 +658,7 @@ bool wxFloatProperty::StringToValue( wxVariant& variant, const wxString& text, i bool res = text.ToDouble(&value); if ( res ) { - if ( m_value != value ) + if ( variant != value ) { variant = value; return true; @@ -613,66 +670,25 @@ bool wxFloatProperty::StringToValue( wxVariant& variant, const wxString& text, i return false; } -bool wxFloatProperty::DoValidation( const wxPGProperty* property, double& value, wxPGValidationInfo* pValidationInfo, int mode ) +bool wxFloatProperty::DoValidation( const wxPGProperty* property, + double& value, + wxPGValidationInfo* pValidationInfo, + int mode ) { - // Check for min/max - double min = (double)wxINT64_MIN; - double max = (double)wxINT64_MAX; - wxVariant variant; - bool minOk = false; - bool maxOk = false; - - variant = property->GetAttribute(wxPGGlobalVars->m_strMin); - if ( !variant.IsNull() ) - { - wxPGVariantToDouble(variant, &min); - minOk = true; - } - - variant = property->GetAttribute(wxPGGlobalVars->m_strMax); - if ( !variant.IsNull() ) - { - wxPGVariantToDouble(variant, &max); - maxOk = true; - } - - if ( minOk ) - { - if ( value < min ) - { - if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE ) - pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %f or higher"),min); - else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE ) - value = min; - else - value = max - (min - value); - return false; - } - } - - if ( maxOk ) - { - wxPGVariantToDouble(variant, &max); - if ( value > max ) - { - if ( mode == wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE ) - pValidationInfo->m_failureMessage = wxString::Format(_("Value must be %f or less"),max); - else if ( mode == wxPG_PROPERTY_VALIDATION_SATURATE ) - value = max; - else - value = min + (value - max); - return false; - } - } - return true; + return NumericValidation(property, + value, + pValidationInfo, + mode, + wxS("%g")); } -bool wxFloatProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const +bool +wxFloatProperty::ValidateValue( wxVariant& value, + wxPGValidationInfo& validationInfo ) const { - double fpv; - if ( wxPGVariantToDouble(value, &fpv) ) - return DoValidation(this, fpv, &validationInfo, wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE); - return true; + double fpv = value.GetDouble(); + return DoValidation(this, fpv, &validationInfo, + wxPG_PROPERTY_VALIDATION_ERROR_MESSAGE); } bool wxFloatProperty::DoSetAttribute( const wxString& name, wxVariant& value ) @@ -704,16 +720,18 @@ const wxPGEditor* wxBoolProperty::DoGetEditorClass() const // Select correct editor control. #if wxPG_INCLUDE_CHECKBOX if ( !(m_flags & wxPG_PROP_USE_CHECKBOX) ) - return wxPG_EDITOR(Choice); - return wxPG_EDITOR(CheckBox); + return wxPGEditor_Choice; + return wxPGEditor_CheckBox; #else - return wxPG_EDITOR(Choice); + return wxPGEditor_Choice; #endif } wxBoolProperty::wxBoolProperty( const wxString& label, const wxString& name, bool value ) : wxPGProperty(label,name) { + m_choices.Assign(wxPGGlobalVars->m_boolChoices); + SetValue(wxPGVariant_Bool(value)); m_flags |= wxPG_PROP_USE_DCC; @@ -721,15 +739,16 @@ wxBoolProperty::wxBoolProperty( const wxString& label, const wxString& name, boo wxBoolProperty::~wxBoolProperty() { } -wxString wxBoolProperty::GetValueAsString( int argFlags ) const +wxString wxBoolProperty::ValueToString( wxVariant& value, + int argFlags ) const { - bool value = m_value.GetBool(); + bool boolValue = value.GetBool(); // As a fragment of composite string value, // make it a little more readable. if ( argFlags & wxPG_COMPOSITE_FRAGMENT ) { - if ( value ) + if ( boolValue ) { return m_label; } @@ -738,46 +757,36 @@ wxString wxBoolProperty::GetValueAsString( int argFlags ) const if ( argFlags & wxPG_UNEDITABLE_COMPOSITE_FRAGMENT ) return wxEmptyString; - const wxChar* notFmt; + wxString notFmt; if ( wxPGGlobalVars->m_autoGetTranslation ) notFmt = _("Not %s"); else - notFmt = wxT("Not %s"); + notFmt = wxS("Not %s"); - return wxString::Format(notFmt,m_label.c_str()); + return wxString::Format(notFmt.c_str(), m_label.c_str()); } } if ( !(argFlags & wxPG_FULL_VALUE) ) { - return wxPGGlobalVars->m_boolChoices[value?1:0].GetText(); + return wxPGGlobalVars->m_boolChoices[boolValue?1:0].GetText(); } wxString text; - if (value) text = wxS("true"); + if ( boolValue ) text = wxS("true"); else text = wxS("false"); return text; } -int wxBoolProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo ) -{ - if ( IsValueUnspecified() ) - return -1; - - if ( choiceinfo ) - choiceinfo->m_choices = &wxPGGlobalVars->m_boolChoices; - return m_value.GetBool()?1:0; -} - bool wxBoolProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const { - int value = 0; + bool boolValue = false; if ( text.CmpNoCase(wxPGGlobalVars->m_boolChoices[1].GetText()) == 0 || text.CmpNoCase(wxS("true")) == 0 || text.CmpNoCase(m_label) == 0 ) - value = 1; + boolValue = true; if ( text.length() == 0 ) { @@ -785,11 +794,9 @@ bool wxBoolProperty::StringToValue( wxVariant& variant, const wxString& text, in return true; } - bool oldValue = m_value.GetBool(); - - if ( (oldValue && !value) || (!oldValue && value) ) + if ( variant != boolValue ) { - variant = wxPGVariant_Bool(value); + variant = wxPGVariant_Bool(boolValue); return true; } return false; @@ -798,9 +805,8 @@ bool wxBoolProperty::StringToValue( wxVariant& variant, const wxString& text, in bool wxBoolProperty::IntToValue( wxVariant& variant, int value, int ) const { bool boolValue = value ? true : false; - bool oldValue = m_value.GetBool(); - if ( oldValue != boolValue ) + if ( variant != boolValue ) { variant = wxPGVariant_Bool(boolValue); return true; @@ -813,8 +819,7 @@ bool wxBoolProperty::DoSetAttribute( const wxString& name, wxVariant& value ) #if wxPG_INCLUDE_CHECKBOX if ( name == wxPG_BOOL_USE_CHECKBOX ) { - int ival = wxPGVariantToInt(value); - if ( ival ) + if ( value.GetLong() ) m_flags |= wxPG_PROP_USE_CHECKBOX; else m_flags &= ~(wxPG_PROP_USE_CHECKBOX); @@ -823,8 +828,7 @@ bool wxBoolProperty::DoSetAttribute( const wxString& name, wxVariant& value ) #endif if ( name == wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING ) { - int ival = wxPGVariantToInt(value); - if ( ival ) + if ( value.GetLong() ) m_flags |= wxPG_PROP_USE_DCC; else m_flags &= ~(wxPG_PROP_USE_DCC); @@ -834,33 +838,108 @@ bool wxBoolProperty::DoSetAttribute( const wxString& name, wxVariant& value ) } // ----------------------------------------------------------------------- -// wxBaseEnumProperty +// wxEnumProperty // ----------------------------------------------------------------------- -int wxBaseEnumProperty::ms_nextIndex = -2; +IMPLEMENT_DYNAMIC_CLASS(wxEnumProperty, wxPGProperty) -wxBaseEnumProperty::wxBaseEnumProperty( const wxString& label, const wxString& name ) +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty,long,Choice) + +wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, const wxChar* const* labels, + const long* values, int value ) : wxPGProperty(label,name) +{ + SetIndex(0); + + if ( labels ) + { + m_choices.Add(labels,values); + + if ( GetItemCount() ) + SetValue( (long)value ); + } +} + +wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, const wxChar* const* labels, + const long* values, wxPGChoices* choicesCache, int value ) + : wxPGProperty(label,name) +{ + SetIndex(0); + + wxASSERT( choicesCache ); + + if ( choicesCache->IsOk() ) + { + m_choices.Assign( *choicesCache ); + m_value = wxPGVariant_Zero; + } + else if ( labels ) + { + m_choices.Add(labels,values); + + if ( GetItemCount() ) + SetValue( (long)value ); + } +} + +wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, int value ) + : wxPGProperty(label,name) +{ + SetIndex(0); + + if ( &labels && labels.size() ) + { + m_choices.Set(labels, values); + + if ( GetItemCount() ) + SetValue( (long)value ); + } +} + +wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, + wxPGChoices& choices, int value ) : wxPGProperty(label,name) { - m_value = wxPGVariant_Zero; + m_choices.Assign( choices ); + + if ( GetItemCount() ) + SetValue( (long)value ); } -/** If has values array, then returns number at index with value - - otherwise just returns the value. -*/ -int wxBaseEnumProperty::GetIndexForValue( int value ) const +int wxEnumProperty::GetIndexForValue( int value ) const { + if ( !m_choices.IsOk() ) + return -1; + + int intVal = m_choices.Index(value); + if ( intVal >= 0 ) + return intVal; + return value; } -void wxBaseEnumProperty::OnSetValue() +wxEnumProperty::~wxEnumProperty () { - if ( wxPGIsVariantType(m_value, long) ) +} + +int wxEnumProperty::ms_nextIndex = -2; + +void wxEnumProperty::OnSetValue() +{ + wxString variantType = m_value.GetType(); + + if ( variantType == wxPG_VARIANT_TYPE_LONG ) + { ValueFromInt_( m_value, m_value.GetLong(), wxPG_FULL_VALUE ); - else if ( wxPGIsVariantType(m_value, string) ) + } + else if ( variantType == wxPG_VARIANT_TYPE_STRING ) + { ValueFromString_( m_value, m_value.GetString(), 0 ); + } else - wxASSERT( false ); + { + wxFAIL; + } if ( ms_nextIndex != -2 ) { @@ -869,64 +948,55 @@ void wxBaseEnumProperty::OnSetValue() } } -bool wxBaseEnumProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& WXUNUSED(validationInfo) ) const +bool wxEnumProperty::ValidateValue( wxVariant& value, wxPGValidationInfo& WXUNUSED(validationInfo) ) const { // Make sure string value is in the list, // unless property has string as preferred value type // To reduce code size, use conversion here as well - if ( wxPGIsVariantType(value, string) && + if ( value.GetType() == wxPG_VARIANT_TYPE_STRING && !this->IsKindOf(CLASSINFO(wxEditEnumProperty)) ) return ValueFromString_( value, value.GetString(), wxPG_PROPERTY_SPECIFIC ); return true; } -wxString wxBaseEnumProperty::GetValueAsString( int ) const +wxString wxEnumProperty::ValueToString( wxVariant& value, + int WXUNUSED(argFlags) ) const { - if ( wxPGIsVariantType(m_value, string) ) - return m_value.GetString(); + if ( value.GetType() == wxPG_VARIANT_TYPE_STRING ) + return value.GetString(); - if ( m_index >= 0 ) - { - int unusedVal; - const wxString* pstr = GetEntry( m_index, &unusedVal ); + int index = m_choices.Index(value.GetLong()); + if ( index < 0 ) + return wxEmptyString; - if ( pstr ) - return *pstr; - } - return wxEmptyString; + return m_choices.GetLabel(index); } -bool wxBaseEnumProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const +bool wxEnumProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const { return ValueFromString_( variant, text, argFlags ); } -bool wxBaseEnumProperty::IntToValue( wxVariant& variant, int intVal, int argFlags ) const +bool wxEnumProperty::IntToValue( wxVariant& variant, int intVal, int argFlags ) const { return ValueFromInt_( variant, intVal, argFlags ); } -bool wxBaseEnumProperty::ValueFromString_( wxVariant& value, const wxString& text, int argFlags ) const +bool wxEnumProperty::ValueFromString_( wxVariant& value, const wxString& text, int argFlags ) const { - size_t i = 0; - const wxString* entryLabel; - int entryValue; int useIndex = -1; long useValue = 0; - entryLabel = GetEntry(i, &entryValue); - while ( entryLabel ) + for ( unsigned int i=0; iIsOk() ) - { - m_choices.Assign( *choicesCache ); - m_value = wxPGVariant_Zero; - } - else if ( labels ) - { - m_choices.Add(labels,values); - - if ( GetItemCount() ) - SetValue( (long)value ); - } -} - -wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, - const wxArrayString& labels, const wxArrayInt& values, int value ) : wxBaseEnumProperty(label,name) -{ - SetIndex(0); - - if ( &labels && labels.size() ) - { - m_choices.Set(labels, values); - - if ( GetItemCount() ) - SetValue( (long)value ); - } -} - -wxEnumProperty::wxEnumProperty( const wxString& label, const wxString& name, - wxPGChoices& choices, int value ) - : wxBaseEnumProperty(label,name) -{ - m_choices.Assign( choices ); - - if ( GetItemCount() ) - SetValue( (long)value ); + ms_nextIndex = -2; + m_index = index; } -int wxEnumProperty::GetIndexForValue( int value ) const +int wxEnumProperty::GetIndex() const { - if ( !m_choices.IsOk() ) + if ( m_value.IsNull() ) return -1; - if ( m_choices.HasValues() ) - { - int intVal = m_choices.Index(value); - if ( intVal >= 0 ) - return intVal; - } - - return value; -} - -wxEnumProperty::~wxEnumProperty () -{ -} - -const wxString* wxEnumProperty::GetEntry( size_t index, int* pvalue ) const -{ - if ( m_choices.IsOk() && index < m_choices.GetCount() ) - { - int value = (int)index; - if ( m_choices.HasValue(index) ) - value = m_choices.GetValue(index); - - if ( pvalue ) - *pvalue = value; - - return &m_choices.GetLabel(index); - } - return (const wxString*) NULL; -} - -int wxEnumProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo ) -{ - if ( choiceinfo ) - choiceinfo->m_choices = &m_choices; - - if ( !m_choices.IsOk() ) - return -1; + if ( ms_nextIndex != -2 ) + return ms_nextIndex; - return GetIndex(); + return m_index; } // ----------------------------------------------------------------------- @@ -1144,14 +1109,14 @@ IMPLEMENT_DYNAMIC_CLASS(wxEditEnumProperty, wxPGProperty) WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty,wxString,ComboBox) -wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels, +wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar* const* labels, const long* values, const wxString& value ) : wxEnumProperty(label,name,labels,values,0) { SetValue( value ); } -wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels, +wxEditEnumProperty::wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar* const* labels, const long* values, wxPGChoices* choicesCache, const wxString& value ) : wxEnumProperty(label,name,labels,values,choicesCache,0) { @@ -1186,9 +1151,6 @@ WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxFlagsProperty,long,TextCtrl) void wxFlagsProperty::Init() { - SetFlag(wxPG_PROP_AGGREGATE); // This is must be done here to support flag props - // with inital zero children. - long value = m_value; // @@ -1196,7 +1158,7 @@ void wxFlagsProperty::Init() // unsigned int i; - unsigned int prevChildCount = m_children.GetCount(); + unsigned int prevChildCount = m_children.size(); int oldSel = -1; if ( prevChildCount ) @@ -1212,7 +1174,7 @@ void wxFlagsProperty::Init() if ( selected ) { if ( selected->GetParent() == this ) - oldSel = selected->GetArrIndex(); + oldSel = selected->GetIndexInParent(); else if ( selected == this ) oldSel = -2; } @@ -1222,9 +1184,15 @@ void wxFlagsProperty::Init() // Delete old children for ( i=0; im_autoGetTranslation ) { - boolProp = new wxBoolProperty( ::wxGetTranslation( GetLabel(i) ), wxEmptyString, child_val ); + boolProp = new wxBoolProperty( ::wxGetTranslation(label), label, child_val ); } else #endif { - boolProp = new wxBoolProperty( GetLabel(i), wxEmptyString, child_val ); + boolProp = new wxBoolProperty( label, label, child_val ); } - AddChild(boolProp); + if ( attrUseCheckBox ) + boolProp->SetAttribute(wxPG_BOOL_USE_CHECKBOX, + true); + if ( attrUseDCC ) + boolProp->SetAttribute(wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING, + true); + AddPrivateChild(boolProp); } m_oldChoicesData = m_choices.GetDataPtr(); @@ -1263,9 +1235,9 @@ void wxFlagsProperty::Init() } wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name, - const wxChar** labels, const long* values, long value ) : wxPGProperty(label,name) + const wxChar* const* labels, const long* values, long value ) : wxPGProperty(label,name) { - m_oldChoicesData = (wxPGChoicesData*) NULL; + m_oldChoicesData = NULL; if ( labels ) { @@ -1285,7 +1257,7 @@ wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name, const wxArrayString& labels, const wxArrayInt& values, int value ) : wxPGProperty(label,name) { - m_oldChoicesData = (wxPGChoicesData*) NULL; + m_oldChoicesData = NULL; if ( &labels && labels.size() ) { @@ -1305,7 +1277,7 @@ wxFlagsProperty::wxFlagsProperty( const wxString& label, const wxString& name, wxPGChoices& choices, long value ) : wxPGProperty(label,name) { - m_oldChoicesData = (wxPGChoicesData*) NULL; + m_oldChoicesData = NULL; if ( choices.IsOk() ) { @@ -1342,10 +1314,7 @@ void wxFlagsProperty::OnSetValue() const wxPGChoices& choices = m_choices; for ( i = 0; i < GetItemCount(); i++ ) { - if ( choices.HasValue(i) ) - fullFlags |= choices.GetValue(i); - else - fullFlags |= (1<SetFlag( wxPG_PROP_MODIFIED ); @@ -1384,24 +1350,22 @@ void wxFlagsProperty::OnSetValue() } } -wxString wxFlagsProperty::GetValueAsString( int ) const +wxString wxFlagsProperty::ValueToString( wxVariant& value, + int WXUNUSED(argFlags) ) const { wxString text; if ( !m_choices.IsOk() ) return text; - long flags = m_value; + long flags = value; unsigned int i; const wxPGChoices& choices = m_choices; for ( i = 0; i < GetItemCount(); i++ ) { int doAdd; - if ( choices.HasValue(i) ) - doAdd = ( flags & choices.GetValue(i) ); - else - doAdd = ( flags & (1<m_choices = &m_choices; - return -1; + if ( name == wxPG_BOOL_USE_CHECKBOX || + name == wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING ) + { + for ( size_t i=0; iSetAttribute(name, value); + } + // Must return false so that the attribute is stored in + // flag property's actual property storage + return false; + } + return false; } // ----------------------------------------------------------------------- // wxDirProperty // ----------------------------------------------------------------------- -WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxDirProperty,wxLongStringProperty,const wxString&) +IMPLEMENT_DYNAMIC_CLASS(wxDirProperty, wxLongStringProperty) wxDirProperty::wxDirProperty( const wxString& name, const wxString& label, const wxString& value ) : wxLongStringProperty(name,label,value) { - m_flags |= wxPG_NO_ESCAPE; + m_flags |= wxPG_PROP_NO_ESCAPE; } + wxDirProperty::~wxDirProperty() { } wxValidator* wxDirProperty::DoGetValidator() const @@ -1539,19 +1510,24 @@ wxValidator* wxDirProperty::DoGetValidator() const bool wxDirProperty::OnButtonClick( wxPropertyGrid* propGrid, wxString& value ) { + // Update property value from editor, if necessary wxSize dlg_sz(300,400); + wxString dlgMessage(m_dlgMessage); + if ( dlgMessage.empty() ) + dlgMessage = _("Choose a directory:"); wxDirDialog dlg( propGrid, - m_dlgMessage.length() ? m_dlgMessage : wxString(_("Choose a directory:")), + dlgMessage, value, 0, #if !wxPG_SMALL_SCREEN propGrid->GetGoodEditorDialogPosition(this,dlg_sz), - dlg_sz ); + dlg_sz #else wxDefaultPosition, - wxDefaultSize ); + wxDefaultSize #endif + ); if ( dlg.ShowModal() == wxID_OK ) { @@ -1584,7 +1560,8 @@ bool wxPGFileDialogAdapter::DoShowDialog( wxPropertyGrid* propGrid, wxPGProperty if ( property->IsKindOf(CLASSINFO(wxFileProperty)) ) { fileProp = ((wxFileProperty*)property); - path = fileProp->m_filename.GetPath(); + wxFileName filename = fileProp->GetValue().GetString(); + path = filename.GetPath(); indFilter = fileProp->m_indFilter; if ( !path.length() && fileProp->m_basePath.length() ) @@ -1636,10 +1613,9 @@ wxFileProperty::wxFileProperty( const wxString& label, const wxString& name, wxFileProperty::~wxFileProperty() {} -#if wxUSE_VALIDATORS - wxValidator* wxFileProperty::GetClassValidator() { +#if wxUSE_VALIDATORS WX_PG_DOGETVALIDATOR_ENTRY() // Atleast wxPython 2.6.2.1 required that the string argument is given @@ -1657,6 +1633,9 @@ wxValidator* wxFileProperty::GetClassValidator() validator->SetExcludes(exChars); WX_PG_DOGETVALIDATOR_EXIT(validator) +#else + return NULL; +#endif } wxValidator* wxFileProperty::DoGetValidator() const @@ -1664,24 +1643,21 @@ wxValidator* wxFileProperty::DoGetValidator() const return GetClassValidator(); } -#endif - void wxFileProperty::OnSetValue() { const wxString& fnstr = m_value.GetString(); - m_filename = fnstr; + wxFileName filename = fnstr; - if ( !m_filename.HasName() ) + if ( !filename.HasName() ) { m_value = wxPGVariant_EmptyString; - m_filename.Clear(); } // Find index for extension. if ( m_indFilter < 0 && fnstr.length() ) { - wxString ext = m_filename.GetExt(); + wxString ext = filename.GetExt(); int curind = 0; size_t pos = 0; size_t len = m_wildcard.length(); @@ -1718,29 +1694,44 @@ void wxFileProperty::OnSetValue() } } -wxString wxFileProperty::GetValueAsString( int argFlags ) const +wxFileName wxFileProperty::GetFileName() const { - // Always return empty string when name component is empty - wxString fullName = m_filename.GetFullName(); + wxFileName filename; + + if ( !m_value.IsNull() ) + filename = m_value.GetString(); + + return filename; +} + +wxString wxFileProperty::ValueToString( wxVariant& value, + int argFlags ) const +{ + wxFileName filename = value.GetString(); + + if ( !filename.HasName() ) + return wxEmptyString; + + wxString fullName = filename.GetFullName(); if ( !fullName.length() ) - return fullName; + return wxEmptyString; if ( argFlags & wxPG_FULL_VALUE ) { - return m_filename.GetFullPath(); + return filename.GetFullPath(); } else if ( m_flags & wxPG_PROP_SHOW_FULL_FILENAME ) { if ( m_basePath.Length() ) { - wxFileName fn2(m_filename); + wxFileName fn2(filename); fn2.MakeRelativeTo(m_basePath); return fn2.GetFullPath(); } - return m_filename.GetFullPath(); + return filename.GetFullPath(); } - return m_filename.GetFullName(); + return filename.GetFullName(); } wxPGEditorDialogAdapter* wxFileProperty::GetEditorDialog() const @@ -1750,9 +1741,11 @@ wxPGEditorDialogAdapter* wxFileProperty::GetEditorDialog() const bool wxFileProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const { + wxFileName filename = variant.GetString(); + if ( (m_flags & wxPG_PROP_SHOW_FULL_FILENAME) || (argFlags & wxPG_FULL_VALUE) ) { - if ( m_filename != text ) + if ( filename != text ) { variant = text; return true; @@ -1760,9 +1753,9 @@ bool wxFileProperty::StringToValue( wxVariant& variant, const wxString& text, in } else { - if ( m_filename.GetFullName() != text ) + if ( filename.GetFullName() != text ) { - wxFileName fn = m_filename; + wxFileName fn = filename; fn.SetFullName(text); variant = fn.GetFullPath(); return true; @@ -1778,7 +1771,7 @@ bool wxFileProperty::DoSetAttribute( const wxString& name, wxVariant& value ) // stored in m_attributes. if ( name == wxPG_FILE_SHOW_FULL_PATH ) { - if ( wxPGVariantToInt(value) ) + if ( value.GetLong() ) m_flags |= wxPG_PROP_SHOW_FULL_FILENAME; else m_flags &= ~(wxPG_PROP_SHOW_FULL_FILENAME); @@ -1855,9 +1848,10 @@ wxLongStringProperty::wxLongStringProperty( const wxString& label, const wxStrin wxLongStringProperty::~wxLongStringProperty() {} -wxString wxLongStringProperty::GetValueAsString( int ) const +wxString wxLongStringProperty::ValueToString( wxVariant& value, + int WXUNUSED(argFlags) ) const { - return m_value; + return value; } bool wxLongStringProperty::OnEvent( wxPropertyGrid* propGrid, wxWindow* WXUNUSED(primary), @@ -1866,9 +1860,9 @@ bool wxLongStringProperty::OnEvent( wxPropertyGrid* propGrid, wxWindow* WXUNUSED if ( propGrid->IsMainButtonEvent(event) ) { // Update the value - PrepareValueForDialogEditing(propGrid); + wxVariant useValue = propGrid->GetUncommittedPropertyValue(); - wxString val1 = GetValueAsString(0); + wxString val1 = useValue.GetString(); wxString val_orig = val1; wxString value; @@ -1922,14 +1916,14 @@ bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty* prop, wxPropertyGr rowsizer->Add( ed, 1, wxEXPAND|wxALL, spacing ); topsizer->Add( rowsizer, 1, wxEXPAND, 0 ); - rowsizer = new wxBoxSizer( wxHORIZONTAL ); - const int but_sz_flags = - wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT; - rowsizer->Add( new wxButton(dlg,wxID_OK,_("Ok")), - 0, but_sz_flags, spacing ); - rowsizer->Add( new wxButton(dlg,wxID_CANCEL,_("Cancel")), - 0, but_sz_flags, spacing ); - topsizer->Add( rowsizer, 0, wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL, 0 ); + + wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer(); + buttonSizer->AddButton(new wxButton(dlg, wxID_OK)); + buttonSizer->AddButton(new wxButton(dlg, wxID_CANCEL)); + buttonSizer->Realize(); + topsizer->Add( buttonSizer, 0, + wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxRIGHT, + spacing ); dlg->SetSizer( topsizer ); topsizer->SetSizeHints( dlg ); @@ -1954,7 +1948,7 @@ bool wxLongStringProperty::DisplayEditorDialog( wxPGProperty* prop, wxPropertyGr bool wxLongStringProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const { - if ( m_value != text ) + if ( variant != text ) { variant = text; return true; @@ -1962,70 +1956,49 @@ bool wxLongStringProperty::StringToValue( wxVariant& variant, const wxString& te return false; } +#if wxUSE_EDITABLELISTBOX + // ----------------------------------------------------------------------- -// wxArrayEditorDialog +// wxPGArrayEditorDialog // ----------------------------------------------------------------------- -BEGIN_EVENT_TABLE(wxArrayEditorDialog, wxDialog) - EVT_IDLE(wxArrayEditorDialog::OnIdle) - EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick) - EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick) - EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick) - EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick) - EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick) - EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick) - EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick) - //EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick) +BEGIN_EVENT_TABLE(wxPGArrayEditorDialog, wxDialog) + EVT_IDLE(wxPGArrayEditorDialog::OnIdle) END_EVENT_TABLE() -IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog, wxDialog) +IMPLEMENT_ABSTRACT_CLASS(wxPGArrayEditorDialog, wxDialog) -#include +#include "wx/editlbox.h" +#include "wx/listctrl.h" // ----------------------------------------------------------------------- -void wxArrayEditorDialog::OnIdle(wxIdleEvent& event) +void wxPGArrayEditorDialog::OnIdle(wxIdleEvent& event) { - // - // Do control focus detection here. - // + // Repair focus - wxEditableListBox has bitmap buttons, which + // get focus, and lose focus (into the oblivion) when they + // become disabled due to change in control state. - wxWindow* focused = FindFocus(); + wxWindow* lastFocused = m_lastFocused; + wxWindow* focus = ::wxWindow::FindFocus(); - // This strange focus thing is a workaround for wxGTK wxListBox focus - // reporting bug. - if ( m_curFocus == 0 && focused != m_edValue && - focused != m_butAdd && focused != m_butUpdate && - m_lbStrings->GetSelection() >= 0 ) + // If last focused control became disabled, set focus back to + // wxEditableListBox + if ( lastFocused && focus != lastFocused && + lastFocused->GetParent() == m_elbSubPanel && + !lastFocused->IsEnabled() ) { - // ListBox was just focused. - m_butAdd->Enable(false); - m_butUpdate->Enable(false); - m_butRemove->Enable(true); - m_butUp->Enable(true); - m_butDown->Enable(true); - m_curFocus = 1; - } - else if ( (m_curFocus == 1 && focused == m_edValue) /*|| m_curFocus == 2*/ ) - { - // TextCtrl was just focused. - m_butAdd->Enable(true); - bool upd_enable = false; - if ( m_lbStrings->GetCount() && m_lbStrings->GetSelection() >= 0 ) - upd_enable = true; - m_butUpdate->Enable(upd_enable); - m_butRemove->Enable(false); - m_butUp->Enable(false); - m_butDown->Enable(false); - m_curFocus = 0; + m_elb->GetListCtrl()->SetFocus(); } + m_lastFocused = focus; + event.Skip(); } // ----------------------------------------------------------------------- -wxArrayEditorDialog::wxArrayEditorDialog() +wxPGArrayEditorDialog::wxPGArrayEditorDialog() : wxDialog() { Init(); @@ -2033,14 +2006,16 @@ wxArrayEditorDialog::wxArrayEditorDialog() // ----------------------------------------------------------------------- -void wxArrayEditorDialog::Init() +void wxPGArrayEditorDialog::Init() { - m_custBtText = (const wxChar*) NULL; + m_lastFocused = NULL; + m_hasCustomNewAction = false; + m_itemPendingAtIndex = -1; } // ----------------------------------------------------------------------- -wxArrayEditorDialog::wxArrayEditorDialog( wxWindow *parent, +wxPGArrayEditorDialog::wxPGArrayEditorDialog( wxWindow *parent, const wxString& message, const wxString& caption, long style, @@ -2054,7 +2029,7 @@ wxArrayEditorDialog::wxArrayEditorDialog( wxWindow *parent, // ----------------------------------------------------------------------- -bool wxArrayEditorDialog::Create( wxWindow *parent, +bool wxPGArrayEditorDialog::Create( wxWindow *parent, const wxString& message, const wxString& caption, long style, @@ -2064,6 +2039,7 @@ bool wxArrayEditorDialog::Create( wxWindow *parent, // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION // FIXME: This should be only a temporary fix. #ifdef __WXMAC__ + wxUnusedVar(style); int useStyle = wxCAPTION; #else int useStyle = style; @@ -2081,11 +2057,6 @@ bool wxArrayEditorDialog::Create( wxWindow *parent, m_modified = false; - m_curFocus = 1; - - const int but_sz_flags = - wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxALL; //wxBOTTOM|wxLEFT|wxRIGHT; - wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL ); // Message @@ -2093,81 +2064,60 @@ bool wxArrayEditorDialog::Create( wxWindow *parent, topsizer->Add( new wxStaticText(this,-1,message), 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing ); - // String editor - wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL ); - m_edValue = new wxTextCtrl(this,21,wxEmptyString, - wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER); - wxValidator* validator = GetTextCtrlValidator(); - if ( validator ) - { - m_edValue->SetValidator( *validator ); - delete validator; - } - rowsizer->Add( m_edValue, - 1, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing ); - - // Add button - m_butAdd = new wxButton(this,22,_("Add")); - rowsizer->Add( m_butAdd, - 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, spacing ); - topsizer->Add( rowsizer, 0, wxEXPAND, spacing ); + m_elb = new wxEditableListBox(this, wxID_ANY, message, + wxDefaultPosition, + wxDefaultSize, + wxEL_ALLOW_NEW | + wxEL_ALLOW_EDIT | + wxEL_ALLOW_DELETE); - // Separator line - topsizer->Add( new wxStaticLine(this,-1), - 0, wxEXPAND|wxBOTTOM|wxLEFT|wxRIGHT, spacing ); - - rowsizer = new wxBoxSizer( wxHORIZONTAL ); - - // list box - m_lbStrings = new wxListBox(this, 24, wxDefaultPosition, wxDefaultSize); - unsigned int i; - for ( i=0; iAppend( ArrayGet(i) ); - rowsizer->Add( m_lbStrings, 1, wxEXPAND|wxRIGHT, spacing ); - - // Manipulator buttons - wxBoxSizer* colsizer = new wxBoxSizer( wxVERTICAL ); - m_butCustom = (wxButton*) NULL; - if ( m_custBtText ) - { - m_butCustom = new wxButton(this,28,::wxGetTranslation(m_custBtText)); - colsizer->Add( m_butCustom, - 0, wxALIGN_CENTER|wxTOP/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/, - spacing ); - } - m_butUpdate = new wxButton(this,27,_("Update")); - colsizer->Add( m_butUpdate, - 0, wxALIGN_CENTER|wxTOP, spacing ); - m_butRemove = new wxButton(this,23,_("Remove")); - colsizer->Add( m_butRemove, - 0, wxALIGN_CENTER|wxTOP, spacing ); - m_butUp = new wxButton(this,25,_("Up")); - colsizer->Add( m_butUp, - 0, wxALIGN_CENTER|wxTOP, spacing ); - m_butDown = new wxButton(this,26,_("Down")); - colsizer->Add( m_butDown, - 0, wxALIGN_CENTER|wxTOP, spacing ); - rowsizer->Add( colsizer, 0, 0, spacing ); - - topsizer->Add( rowsizer, 1, wxLEFT|wxRIGHT|wxEXPAND, spacing ); - - // Separator line - topsizer->Add( new wxStaticLine(this,-1), - 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, spacing ); - - // buttons - rowsizer = new wxBoxSizer( wxHORIZONTAL ); - /* - const int but_sz_flags = - wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT; - */ - rowsizer->Add( new wxButton(this,wxID_OK,_("Ok")), - 0, but_sz_flags, spacing ); - rowsizer->Add( new wxButton(this,wxID_CANCEL,_("Cancel")), - 0, but_sz_flags, spacing ); - topsizer->Add( rowsizer, 0, wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL, 0 ); - - m_edValue->SetFocus(); + // Populate the list box + wxArrayString arr; + for ( unsigned int i=0; iSetStrings(arr); + + // Connect event handlers + wxButton* but; + wxListCtrl* lc = m_elb->GetListCtrl(); + + but = m_elb->GetNewButton(); + m_elbSubPanel = but->GetParent(); + but->Connect(but->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxPGArrayEditorDialog::OnAddClick), + NULL, this); + + but = m_elb->GetDelButton(); + but->Connect(but->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxPGArrayEditorDialog::OnDeleteClick), + NULL, this); + + but = m_elb->GetUpButton(); + but->Connect(but->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxPGArrayEditorDialog::OnUpClick), + NULL, this); + + but = m_elb->GetDownButton(); + but->Connect(but->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxPGArrayEditorDialog::OnDownClick), + NULL, this); + + lc->Connect(lc->GetId(), wxEVT_COMMAND_LIST_END_LABEL_EDIT, + wxListEventHandler(wxPGArrayEditorDialog::OnEndLabelEdit), + NULL, this); + + topsizer->Add( m_elb, 1, wxEXPAND, spacing ); + + // Standard dialog buttons + wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer(); + buttonSizer->AddButton(new wxButton(this, wxID_OK)); + buttonSizer->AddButton(new wxButton(this, wxID_CANCEL)); + buttonSizer->Realize(); + topsizer->Add( buttonSizer, 0, + wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxALL, + spacing ); + + m_elb->SetFocus(); SetSizer( topsizer ); topsizer->SetSizeHints( this ); @@ -2185,108 +2135,139 @@ bool wxArrayEditorDialog::Create( wxWindow *parent, // ----------------------------------------------------------------------- -void wxArrayEditorDialog::OnAddClick(wxCommandEvent& ) +int wxPGArrayEditorDialog::GetSelection() const { - wxString text = m_edValue->GetValue(); - if ( text.length() ) + wxListCtrl* lc = m_elb->GetListCtrl(); + + int index = lc->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if ( index == -1 ) + return wxNOT_FOUND; + + return index; +} + +// ----------------------------------------------------------------------- + +void wxPGArrayEditorDialog::OnAddClick(wxCommandEvent& event) +{ + wxListCtrl* lc = m_elb->GetListCtrl(); + int newItemIndex = lc->GetItemCount() - 1; + + if ( m_hasCustomNewAction ) { - if ( ArrayInsert( text, -1 ) ) + wxString str; + if ( OnCustomNewAction(&str) ) { - m_lbStrings->Append( text ); - m_modified = true; - m_edValue->Clear(); + if ( ArrayInsert(str, newItemIndex) ) + { + lc->InsertItem(newItemIndex, str); + m_modified = true; + } } + + // Do *not* skip the event! We do not want the wxEditableListBox + // to do anything. + } + else + { + m_itemPendingAtIndex = newItemIndex; + + event.Skip(); } } // ----------------------------------------------------------------------- -void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent& ) +void wxPGArrayEditorDialog::OnDeleteClick(wxCommandEvent& event) { - int index = m_lbStrings->GetSelection(); + int index = GetSelection(); if ( index >= 0 ) { ArrayRemoveAt( index ); - m_lbStrings->Delete ( index ); m_modified = true; } + + event.Skip(); } // ----------------------------------------------------------------------- -void wxArrayEditorDialog::OnUpClick(wxCommandEvent& ) +void wxPGArrayEditorDialog::OnUpClick(wxCommandEvent& event) { - int index = m_lbStrings->GetSelection(); + int index = GetSelection(); if ( index > 0 ) { ArraySwap(index-1,index); - /*wxString old_str = m_array[index-1]; - wxString new_str = m_array[index]; - m_array[index-1] = new_str; - m_array[index] = old_str;*/ - m_lbStrings->SetString ( index-1, ArrayGet(index-1) ); - m_lbStrings->SetString ( index, ArrayGet(index) ); - m_lbStrings->SetSelection ( index-1 ); m_modified = true; } + + event.Skip(); } // ----------------------------------------------------------------------- -void wxArrayEditorDialog::OnDownClick(wxCommandEvent& ) +void wxPGArrayEditorDialog::OnDownClick(wxCommandEvent& event) { - int index = m_lbStrings->GetSelection(); - int lastStringIndex = ((int) m_lbStrings->GetCount()) - 1; + wxListCtrl* lc = m_elb->GetListCtrl(); + int index = GetSelection(); + int lastStringIndex = lc->GetItemCount() - 1; if ( index >= 0 && index < lastStringIndex ) { - ArraySwap(index,index+1); - /*wxString old_str = m_array[index+1]; - wxString new_str = m_array[index]; - m_array[index+1] = new_str; - m_array[index] = old_str;*/ - m_lbStrings->SetString ( index+1, ArrayGet(index+1) ); - m_lbStrings->SetString ( index, ArrayGet(index) ); - m_lbStrings->SetSelection ( index+1 ); + ArraySwap(index, index+1); m_modified = true; } + + event.Skip(); } // ----------------------------------------------------------------------- -void wxArrayEditorDialog::OnUpdateClick(wxCommandEvent& ) +void wxPGArrayEditorDialog::OnEndLabelEdit(wxListEvent& event) { - int index = m_lbStrings->GetSelection(); - if ( index >= 0 ) + wxString str = event.GetLabel(); + + if ( m_itemPendingAtIndex >= 0 ) { - wxString str = m_edValue->GetValue(); - if ( ArraySet(index,str) ) + // Add a new item + if ( ArrayInsert(str, m_itemPendingAtIndex) ) { - m_lbStrings->SetString ( index, str ); - //m_array[index] = str; m_modified = true; } + else + { + // Editable list box doesn't really respect Veto(), but + // it recognizes if no text was added, so we simulate + // Veto() using it. + event.m_item.SetText(wxEmptyString); + m_elb->GetListCtrl()->SetItemText(m_itemPendingAtIndex, + wxEmptyString); + + event.Veto(); + } } -} - -// ----------------------------------------------------------------------- - -void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent& ) -{ - int index = m_lbStrings->GetSelection(); - if ( index >= 0 ) + else { - m_edValue->SetValue( m_lbStrings->GetString(index) ); + // Change an existing item + int index = GetSelection(); + wxASSERT( index != wxNOT_FOUND ); + if ( ArraySet(index, str) ) + m_modified = true; + else + event.Veto(); } + + event.Skip(); } +#endif // wxUSE_EDITABLELISTBOX + // ----------------------------------------------------------------------- // wxPGArrayStringEditorDialog // ----------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog, wxArrayEditorDialog) +IMPLEMENT_DYNAMIC_CLASS(wxPGArrayStringEditorDialog, wxPGArrayEditorDialog) -BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog, wxArrayEditorDialog) - EVT_BUTTON(28, wxPGArrayStringEditorDialog::OnCustomEditClick) +BEGIN_EVENT_TABLE(wxPGArrayStringEditorDialog, wxPGArrayEditorDialog) END_EVENT_TABLE() // ----------------------------------------------------------------------- @@ -2330,27 +2311,20 @@ void wxPGArrayStringEditorDialog::ArraySwap( size_t first, size_t second ) } wxPGArrayStringEditorDialog::wxPGArrayStringEditorDialog() - : wxArrayEditorDialog() + : wxPGArrayEditorDialog() { Init(); } void wxPGArrayStringEditorDialog::Init() { - m_pCallingClass = (wxArrayStringProperty*) NULL; + m_pCallingClass = NULL; } -void wxPGArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent& ) +bool +wxPGArrayStringEditorDialog::OnCustomNewAction(wxString* resString) { - wxASSERT( m_pCallingClass ); - wxString str = m_edValue->GetValue(); - if ( m_pCallingClass->OnCustomStringEdit(m_parent,str) ) - { - //m_edValue->SetValue ( str ); - m_lbStrings->Append ( str ); - m_array.Add ( str ); - m_modified = true; - } + return m_pCallingClass->OnCustomStringEdit(m_parent, *resString); } // ----------------------------------------------------------------------- @@ -2368,6 +2342,7 @@ wxArrayStringProperty::wxArrayStringProperty( const wxString& label, const wxArrayString& array ) : wxPGProperty(label,name) { + m_delimiter = '"'; SetValue( array ); } @@ -2378,52 +2353,80 @@ void wxArrayStringProperty::OnSetValue() GenerateValueAsString(); } -wxString wxArrayStringProperty::GetValueAsString( int WXUNUSED(argFlags) ) const +void +wxArrayStringProperty::ConvertArrayToString(const wxArrayString& arr, + wxString* pString, + const wxUniChar& delimiter) const +{ + if ( delimiter == '"' || delimiter == '\'' ) + { + // Quoted strings + ArrayStringToString(*pString, + arr, + delimiter, + Escape | QuoteStrings); + } + else + { + // Regular delimiter + ArrayStringToString(*pString, + arr, + delimiter, + 0); + } +} + +wxString wxArrayStringProperty::ValueToString( wxVariant& WXUNUSED(value), + int argFlags ) const { - return m_display; + // + // If this is called from GetValueAsString(), return cached string + if ( argFlags & wxPG_VALUE_IS_CURRENT ) + { + return m_display; + } + + wxArrayString arr = m_value.GetArrayString(); + wxString s; + ConvertArrayToString(arr, &s, m_delimiter); + return s; } // Converts wxArrayString to a string separated by delimeters and spaces. // preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash // conversion. -void wxPropertyGrid::ArrayStringToString( wxString& dst, const wxArrayString& src, - wxChar preDelim, wxChar postDelim, - int flags ) +void +wxArrayStringProperty::ArrayStringToString( wxString& dst, + const wxArrayString& src, + wxUniChar delimiter, int flags ) { wxString pdr; + wxString preas; unsigned int i; unsigned int itemCount = src.size(); - wxChar preas[2]; - dst.Empty(); - if ( !preDelim ) - preas[0] = 0; - else if ( (flags & 1) ) + if ( flags & Escape ) { - preas[0] = preDelim; - preas[1] = 0; - pdr = wxS("\\"); - pdr += preDelim; + preas = delimiter; + pdr = wxS("\\") + static_cast(delimiter); } if ( itemCount ) dst.append( preas ); - wxASSERT( postDelim ); - wxString postDelimStr(postDelim); - //wxString preDelimStr(preDelim); + wxString delimStr(delimiter); for ( i = 0; i < itemCount; i++ ) { wxString str( src.Item(i) ); // Do some character conversion. - // Convertes \ to \\ and to \ - // Useful when preDelim and postDelim are "\"". - if ( flags & 1 ) + // Converts \ to \\ and $delimiter to \$delimiter + // Useful when quoting. + if ( flags & Escape ) { str.Replace( wxS("\\"), wxS("\\\\"), true ); if ( pdr.length() ) @@ -2434,22 +2437,19 @@ void wxPropertyGrid::ArrayStringToString( wxString& dst, const wxArrayString& sr if ( i < (itemCount-1) ) { - dst.append( postDelimStr ); + dst.append( delimStr ); dst.append( wxS(" ") ); dst.append( preas ); } - else if ( preDelim ) - dst.append( postDelimStr ); + else if ( flags & QuoteStrings ) + dst.append( delimStr ); } } -#define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \ - wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxS('"'),wxS('"'),1); - void wxArrayStringProperty::GenerateValueAsString() { wxArrayString arr = m_value.GetArrayString(); - ARRSTRPROP_ARRAY_TO_STRING(m_display, arr) + ConvertArrayToString(arr, &m_display, m_delimiter); } // Default implementation doesn't do anything. @@ -2458,7 +2458,7 @@ bool wxArrayStringProperty::OnCustomStringEdit( wxWindow*, wxString& ) return false; } -wxArrayEditorDialog* wxArrayStringProperty::CreateEditorDialog() +wxPGArrayEditorDialog* wxArrayStringProperty::CreateEditorDialog() { return new wxPGArrayStringEditorDialog(); } @@ -2468,13 +2468,13 @@ bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid* propGrid, const wxChar* cbt ) { // Update the value - PrepareValueForDialogEditing(propGrid); + wxVariant useValue = propGrid->GetUncommittedPropertyValue(); if ( !propGrid->EditorValidate() ) return false; // Create editor dialog. - wxArrayEditorDialog* dlg = CreateEditorDialog(); + wxPGArrayEditorDialog* dlg = CreateEditorDialog(); #if wxUSE_VALIDATORS wxValidator* validator = GetValidator(); wxPGInDialogValidator dialogValidator; @@ -2485,7 +2485,7 @@ bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid* propGrid, if ( strEdDlg ) strEdDlg->SetCustomButton(cbt, this); - dlg->SetDialogValue( wxVariant(m_value) ); + dlg->SetDialogValue( useValue ); dlg->Create(propGrid, wxEmptyString, m_label); #if !wxPG_SMALL_SCREEN @@ -2507,9 +2507,10 @@ bool wxArrayStringProperty::OnButtonClick( wxPropertyGrid* propGrid, { wxArrayString actualValue = value.GetArrayString(); wxString tempStr; - ARRSTRPROP_ARRAY_TO_STRING(tempStr, actualValue) + ConvertArrayToString(actualValue, &tempStr, m_delimiter); #if wxUSE_VALIDATORS - if ( dialogValidator.DoValidate( propGrid, validator, tempStr ) ) + if ( dialogValidator.DoValidate(propGrid, validator, + tempStr) ) #endif { SetValueInEvent( actualValue ); @@ -2538,25 +2539,48 @@ bool wxArrayStringProperty::OnEvent( wxPropertyGrid* propGrid, return false; } -bool wxArrayStringProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const +bool wxArrayStringProperty::StringToValue( wxVariant& variant, + const wxString& text, int ) const { wxArrayString arr; - WX_PG_TOKENIZER2_BEGIN(text,wxS('"')) + if ( m_delimiter == '"' || m_delimiter == '\'' ) + { + // Quoted strings + WX_PG_TOKENIZER2_BEGIN(text, m_delimiter) - // Need to replace backslashes with empty characters - // (opposite what is done in GenerateValueString). - token.Replace ( wxS("\\"), wxEmptyString, true ); + // Need to replace backslashes with empty characters + // (opposite what is done in ConvertArrayToString()). + token.Replace ( wxS("\\\\"), wxS("\\"), true ); - arr.Add( token ); + arr.Add( token ); - WX_PG_TOKENIZER2_END() + WX_PG_TOKENIZER2_END() + } + else + { + // Regular delimiter + WX_PG_TOKENIZER1_BEGIN(text, m_delimiter) + arr.Add( token ); + WX_PG_TOKENIZER1_END() + } variant = arr; return true; } +bool wxArrayStringProperty::DoSetAttribute( const wxString& name, wxVariant& value ) +{ + if ( name == wxPG_ARRAY_DELIMITER ) + { + m_delimiter = value.GetChar(); + GenerateValueAsString(); + return false; + } + return true; +} + // ----------------------------------------------------------------------- // wxPGInDialogValidator // ----------------------------------------------------------------------- @@ -2600,3 +2624,4 @@ bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* WXUNUSED(propGrid), // ----------------------------------------------------------------------- +#endif // wxUSE_PROPGRID