X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2fd4a52415273bce03708dcdd7af4a4e2523f540..2e14066008229145e2da7b9f05a478ce38631f83:/src/propgrid/advprops.cpp diff --git a/src/propgrid/advprops.cpp b/src/propgrid/advprops.cpp index 2e93e339f7..d0187762de 100644 --- a/src/propgrid/advprops.cpp +++ b/src/propgrid/advprops.cpp @@ -6,7 +6,7 @@ // Created: 2004-09-25 // RCS-ID: $Id$ // Copyright: (c) Jaakko Salli -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". @@ -62,6 +62,8 @@ #include "wx/msw/dc.h" #endif +#include "wx/odcombo.h" + // ----------------------------------------------------------------------- #if defined(__WXMSW__) @@ -80,11 +82,6 @@ // ----------------------------------------------------------------------- -bool operator == (const wxFont&, const wxFont&) -{ - return false; -} - // Implement dynamic class for type value. IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue, wxObject) @@ -113,17 +110,142 @@ bool operator == (const wxArrayInt& array1, const wxArrayInt& array2) #if wxUSE_SPINBTN +#ifdef __WXMSW__ + #define IS_MOTION_SPIN_SUPPORTED 1 +#else + #define IS_MOTION_SPIN_SUPPORTED 0 +#endif + +#if IS_MOTION_SPIN_SUPPORTED + +// +// This class implements ability to rapidly change "spin" value +// by moving mouse when one of the spin buttons is depressed. +class wxPGSpinButton : public wxSpinButton +{ +public: + wxPGSpinButton() : wxSpinButton() + { + m_bLeftDown = false; + m_hasCapture = false; + m_spins = 1; + + Connect( wxEVT_LEFT_DOWN, + wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) ); + Connect( wxEVT_LEFT_UP, + wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) ); + Connect( wxEVT_MOTION, + wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) ); + Connect( wxEVT_MOUSE_CAPTURE_LOST, + wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost) ); + } + + int GetSpins() const + { + return m_spins; + } + +private: + wxPoint m_ptPosition; + + // Having a separate spins variable allows us to handle validation etc. for + // multiple spin events at once (with quick mouse movements there could be + // hundreds of 'spins' being done at once). Technically things like this + // should be stored in event (wxSpinEvent in this case), but there probably + // isn't anything there that can be reliably reused. + int m_spins; + + bool m_bLeftDown; + + // SpinButton seems to be a special for mouse capture, so we may need track + // privately whether mouse is actually captured. + bool m_hasCapture; + + void Capture() + { + if ( !m_hasCapture ) + { + CaptureMouse(); + m_hasCapture = true; + } + + SetCursor(wxCURSOR_SIZENS); + } + void Release() + { + m_bLeftDown = false; + + if ( m_hasCapture ) + { + ReleaseMouse(); + m_hasCapture = false; + } + + wxWindow *parent = GetParent(); + if ( parent ) + SetCursor(parent->GetCursor()); + else + SetCursor(wxNullCursor); + } + + void OnMouseEvent(wxMouseEvent& event) + { + if ( event.GetEventType() == wxEVT_LEFT_DOWN ) + { + m_bLeftDown = true; + m_ptPosition = event.GetPosition(); + } + else if ( event.GetEventType() == wxEVT_LEFT_UP ) + { + Release(); + m_bLeftDown = false; + } + else if ( event.GetEventType() == wxEVT_MOTION ) + { + if ( m_bLeftDown ) + { + int dy = m_ptPosition.y - event.GetPosition().y; + if ( dy ) + { + Capture(); + m_ptPosition = event.GetPosition(); + + wxSpinEvent evtscroll( (dy >= 0) ? wxEVT_SCROLL_LINEUP : + wxEVT_SCROLL_LINEDOWN, + GetId() ); + evtscroll.SetEventObject(this); + + wxASSERT( m_spins == 1 ); + + m_spins = abs(dy); + GetEventHandler()->ProcessEvent(evtscroll); + m_spins = 1; + } + } + } + + event.Skip(); + } + void OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) + { + Release(); + } +}; + +#endif // IS_MOTION_SPIN_SUPPORTED + + WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl, wxPGSpinCtrlEditor, wxPGEditor) -// Trivial destructor. +// Destructor. It is useful to reset the global pointer in it. wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor() { + wxPG_EDITOR(SpinCtrl) = NULL; } - // Create controls and initialize event handling. wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, const wxPoint& pos, const wxSize& sz ) const @@ -133,7 +255,19 @@ wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxP wxSize tcSz(sz.x - butSz.x - margin, sz.y); wxPoint butPos(pos.x + tcSz.x + margin, pos.y); - wxSpinButton* wnd2 = new wxSpinButton(); + wxSpinButton* wnd2; + +#if IS_MOTION_SPIN_SUPPORTED + if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) ) + { + wnd2 = new wxPGSpinButton(); + } + else +#endif + { + wnd2 = new wxSpinButton(); + } + #ifdef __WXMSW__ wnd2->Hide(); #endif @@ -142,23 +276,12 @@ wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxP wnd2->SetRange( INT_MIN, INT_MAX ); wnd2->SetValue( 0 ); - wxWindowID id = wnd2->GetId(); - wnd2->Connect( id, wxEVT_SCROLL_LINEUP, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent), - NULL, propgrid ); - wnd2->Connect( id, wxEVT_SCROLL_LINEDOWN, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent), - NULL, propgrid ); - + wxWindow* wnd1 = wxPGTextCtrlEditor::CreateControls(propgrid, property, pos, tcSz).m_primary; +#if wxUSE_VALIDATORS // Let's add validator to make sure only numbers can be entered wxTextValidator validator(wxFILTER_NUMERIC, &m_tempString); - - wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz ).m_primary; wnd1->SetValidator(validator); - - wnd1->Connect( wnd1->GetId(), wxEVT_KEY_DOWN, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent), - NULL, propgrid ); +#endif return wxPGWindowList(wnd1, wnd2); } @@ -169,6 +292,7 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper { int evtType = event.GetEventType(); int keycode = -1; + int spins = 1; bool bigStep = false; if ( evtType == wxEVT_KEY_DOWN ) @@ -194,6 +318,17 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN ) { + #if IS_MOTION_SPIN_SUPPORTED + if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) ) + { + wxPGSpinButton* spinButton = + (wxPGSpinButton*) propgrid->GetEditorControlSecondary(); + + if ( spinButton ) + spins = spinButton->GetSpins(); + } + #endif + wxString s; // Can't use wnd since it might be clipper window wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl); @@ -219,6 +354,8 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( bigStep ) step *= 10.0; + step *= (double) spins; + if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step; else v_d -= step; @@ -243,6 +380,8 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( bigStep ) step *= 10; + step *= spins; + if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step; else v_ll -= step; @@ -310,6 +449,7 @@ WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl, wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor() { + wxPG_EDITOR(DatePickerCtrl) = NULL; } wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid, @@ -321,7 +461,7 @@ wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgri NULL, wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") ); - wxDateProperty* prop = (wxDateProperty*) property; + wxDateProperty* prop = wxDynamicCast(property, wxDateProperty); // Use two stage creation to allow cleaner display on wxMSW wxDatePickerCtrl* ctrl = new wxDatePickerCtrl(); @@ -332,20 +472,20 @@ wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgri #else wxSize useSz = sz; #endif + + wxDateTime dateValue(wxInvalidDateTime); + + wxVariant value = prop->GetValue(); + if ( value.GetType() == wxT("datetime") ) + dateValue = value.GetDateTime(); + ctrl->Create(propgrid->GetPanel(), wxPG_SUBID1, - prop->GetDateValue(), + dateValue, pos, useSz, prop->GetDatePickerStyle() | wxNO_BORDER); - // Connect all required events to grid's OnCustomEditorEvent - // (all relevenat wxTextCtrl, wxComboBox and wxButton events are - // already connected) - ctrl->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED, - wxCommandEventHandler(wxPropertyGrid::OnCustomEditorEvent), - NULL, propgrid ); - #ifdef __WXMSW__ ctrl->Show(); #endif @@ -354,14 +494,18 @@ wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgri } // Copies value from property to control -void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* wnd ) const +void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property, + wxWindow* wnd ) const { wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd; wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) ); - // We assume that property's data type is 'int' (or something similar), - // thus allowing us to get raw, unchecked value via DoGetValue. - ctrl->SetValue( property->GetValue().GetDateTime() ); + wxDateTime dateValue(wxInvalidDateTime); + wxVariant v(property->GetValue()); + if ( v.GetType() == wxT("datetime") ) + dateValue = v.GetDateTime(); + + ctrl->SetValue( dateValue ); } // Control's events are redirected here @@ -386,11 +530,20 @@ bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProp return true; } -void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(wnd) ) const +void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* property, + wxWindow* wnd ) const { - // TODO? - //wxDateProperty* prop = (wxDateProperty*) property; - //ctrl->SetValue(?); + wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd; + wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) ); + + wxDateProperty* prop = wxDynamicCast(property, wxDateProperty); + + if ( prop ) + { + int datePickerStyle = prop->GetDatePickerStyle(); + if ( datePickerStyle & wxDP_ALLOWNONE ) + ctrl->SetValue(wxInvalidDateTime); + } } #endif // wxUSE_DATEPICKCTRL @@ -403,40 +556,46 @@ void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(pro #include "wx/fontdlg.h" #include "wx/fontenum.h" -static const wxChar* gs_fp_es_family_labels[] = { +// +// NB: Do not use wxS here since unlike wxT it doesn't translate to wxChar* +// + +static const wxChar* const gs_fp_es_family_labels[] = { wxT("Default"), wxT("Decorative"), wxT("Roman"), wxT("Script"), wxT("Swiss"), wxT("Modern"), + wxT("Teletype"), wxT("Unknown"), (const wxChar*) NULL }; -static long gs_fp_es_family_values[] = { - wxDEFAULT, wxDECORATIVE, - wxROMAN, wxSCRIPT, - wxSWISS, wxMODERN +static const long gs_fp_es_family_values[] = { + wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE, + wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT, + wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN, + wxFONTFAMILY_TELETYPE, wxFONTFAMILY_UNKNOWN }; -static const wxChar* gs_fp_es_style_labels[] = { +static const wxChar* const gs_fp_es_style_labels[] = { wxT("Normal"), wxT("Slant"), wxT("Italic"), (const wxChar*) NULL }; -static long gs_fp_es_style_values[] = { +static const long gs_fp_es_style_values[] = { wxNORMAL, wxSLANT, wxITALIC }; -static const wxChar* gs_fp_es_weight_labels[] = { +static const wxChar* const gs_fp_es_weight_labels[] = { wxT("Normal"), wxT("Light"), wxT("Bold"), (const wxChar*) NULL }; -static long gs_fp_es_weight_values[] = { +static const long gs_fp_es_weight_values[] = { wxNORMAL, wxLIGHT, wxBOLD @@ -458,14 +617,7 @@ wxFontProperty::wxFontProperty( const wxString& label, const wxString& name, // Initialize font family choices list if ( !wxPGGlobalVars->m_fontFamilyChoices ) { - wxFontEnumerator enumerator; - enumerator.EnumerateFacenames(); - -#if wxMINOR_VERSION > 6 - wxArrayString faceNames = enumerator.GetFacenames(); -#else - wxArrayString& faceNames = *enumerator.GetFacenames(); -#endif + wxArrayString faceNames = wxFontEnumerator::GetFacenames(); faceNames.Sort(); @@ -477,17 +629,12 @@ wxFontProperty::wxFontProperty( const wxString& label, const wxString& name, wxFont font; font << m_value; - SetParentalType(wxPG_PROP_AGGREGATE); - - AddChild( new wxIntProperty( _("Point Size"), wxS("Point Size"),(long)font.GetPointSize() ) ); - - AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"), - gs_fp_es_family_labels,gs_fp_es_family_values, - font.GetFamily()) ); + AddPrivateChild( new wxIntProperty( _("Point Size"), + wxS("Point Size"),(long)font.GetPointSize() ) ); wxString faceName = font.GetFaceName(); // If font was not in there, add it now - if ( faceName.length() && + if ( !faceName.empty() && wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND ) wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName); @@ -496,16 +643,22 @@ wxFontProperty::wxFontProperty( const wxString& label, const wxString& name, p->SetValueFromString(faceName, wxPG_FULL_VALUE); - AddChild( p ); + AddPrivateChild( p ); - AddChild( new wxEnumProperty(_("Style"), wxS("Style"), - gs_fp_es_style_labels,gs_fp_es_style_values,font.GetStyle()) ); + AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"), + gs_fp_es_style_labels,gs_fp_es_style_values, + font.GetStyle()) ); - AddChild( new wxEnumProperty(_("Weight"), wxS("Weight"), - gs_fp_es_weight_labels,gs_fp_es_weight_values,font.GetWeight()) ); + AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"), + gs_fp_es_weight_labels,gs_fp_es_weight_values, + font.GetWeight()) ); - AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"), - font.GetUnderlined()) ); + AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"), + font.GetUnderlined()) ); + + AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"), + gs_fp_es_family_labels,gs_fp_es_family_values, + font.GetFamily()) ); } wxFontProperty::~wxFontProperty() { } @@ -515,16 +668,16 @@ void wxFontProperty::OnSetValue() wxFont font; font << m_value; - if ( !font.Ok() ) + if ( !font.IsOk() ) { - font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL); - m_value << font; + m_value << *wxNORMAL_FONT; } } -wxString wxFontProperty::GetValueAsString( int argFlags ) const +wxString wxFontProperty::ValueToString( wxVariant& value, + int argFlags ) const { - return wxPGProperty::GetValueAsString(argFlags); + return wxPGProperty::ValueToString(value, argFlags); } bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), @@ -537,7 +690,10 @@ bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(prima wxFontData data; wxFont font; - font << useValue; + + if ( useValue.GetType() == wxS("wxFont") ) + font << useValue; + data.SetInitialFont( font ); data.SetColour(*wxBLACK); @@ -561,31 +717,25 @@ void wxFontProperty::RefreshChildren() wxFont font; font << m_value; Item(0)->SetValue( (long)font.GetPointSize() ); - Item(1)->SetValue( (long)font.GetFamily() ); - Item(2)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE ); - Item(3)->SetValue( (long)font.GetStyle() ); - Item(4)->SetValue( (long)font.GetWeight() ); - Item(5)->SetValue( font.GetUnderlined() ); + Item(1)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE ); + Item(2)->SetValue( (long)font.GetStyle() ); + Item(3)->SetValue( (long)font.GetWeight() ); + Item(4)->SetValue( font.GetUnderlined() ); + Item(5)->SetValue( (long)font.GetFamily() ); } -void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const +wxVariant wxFontProperty::ChildChanged( wxVariant& thisValue, + int ind, + wxVariant& childValue ) const { wxFont font; font << thisValue; if ( ind == 0 ) { - font.SetPointSize( wxPGVariantToInt(childValue) ); + font.SetPointSize( childValue.GetLong() ); } else if ( ind == 1 ) - { - int fam = childValue.GetLong(); - if ( fam < wxDEFAULT || - fam > wxTELETYPE ) - fam = wxDEFAULT; - font.SetFamily( fam ); - } - else if ( ind == 2 ) { wxString faceName; int faceIndex = childValue.GetLong(); @@ -595,7 +745,7 @@ void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& chi font.SetFaceName( faceName ); } - else if ( ind == 3 ) + else if ( ind == 2 ) { int st = childValue.GetLong(); if ( st != wxFONTSTYLE_NORMAL && @@ -604,7 +754,7 @@ void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& chi st = wxFONTWEIGHT_NORMAL; font.SetStyle( st ); } - else if ( ind == 4 ) + else if ( ind == 3 ) { int wt = childValue.GetLong(); if ( wt != wxFONTWEIGHT_NORMAL && @@ -613,12 +763,22 @@ void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& chi wt = wxFONTWEIGHT_NORMAL; font.SetWeight( wt ); } - else if ( ind == 5 ) + else if ( ind == 4 ) { font.SetUnderlined( childValue.GetBool() ); } + else if ( ind == 5 ) + { + int fam = childValue.GetLong(); + if ( fam < wxDEFAULT || + fam > wxTELETYPE ) + fam = wxDEFAULT; + font.SetFamily( fam ); + } - thisValue << font; + wxVariant newVariant; + newVariant << font; + return newVariant; } /* @@ -637,7 +797,7 @@ void wxFontProperty::OnCustomPaint(wxDC& dc, else drawFace = m_value_wxFont.GetFaceName(); - if ( drawFace.length() ) + if ( !drawFace.empty() ) { // Draw the background dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) ); @@ -675,7 +835,7 @@ void wxFontProperty::OnCustomPaint(wxDC& dc, #include "wx/colordlg.h" //#define wx_cp_es_syscolours_len 25 -static const wxChar* gs_cp_es_syscolour_labels[] = { +static const wxChar* const gs_cp_es_syscolour_labels[] = { wxT("AppWorkspace"), wxT("ActiveBorder"), wxT("ActiveCaption"), @@ -704,7 +864,7 @@ static const wxChar* gs_cp_es_syscolour_labels[] = { (const wxChar*) NULL }; -static long gs_cp_es_syscolour_values[] = { +static const long gs_cp_es_syscolour_values[] = { wxSYS_COLOUR_APPWORKSPACE, wxSYS_COLOUR_ACTIVEBORDER, wxSYS_COLOUR_ACTIVECAPTION, @@ -746,7 +906,7 @@ void wxSystemColourProperty::Init( int type, const wxColour& colour ) { wxColourPropertyValue cpv; - if ( colour.Ok() ) + if ( colour.IsOk() ) cpv.Init( type, colour ); else cpv.Init( type, *wxWHITE ); @@ -778,7 +938,7 @@ wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxS wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name, - const wxChar** labels, const long* values, wxPGChoices* choicesCache, + const wxChar* const* labels, const long* values, wxPGChoices* choicesCache, const wxColourPropertyValue& value ) : wxEnumProperty( label, name, labels, values, choicesCache ) { @@ -790,7 +950,7 @@ wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxS wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name, - const wxChar** labels, const long* values, wxPGChoices* choicesCache, + const wxChar* const* labels, const long* values, wxPGChoices* choicesCache, const wxColour& value ) : wxEnumProperty( label, name, labels, values, choicesCache ) { @@ -883,7 +1043,10 @@ wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) con int wxSystemColourProperty::ColToInd( const wxColour& colour ) const { size_t i; - size_t i_max = m_choices.GetCount() - 1; + size_t i_max = m_choices.GetCount(); + + if ( !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) + i_max -= 1; for ( i=0; i>8)&0xFF),((col>>16)&0xFF)); -} - - void wxSystemColourProperty::OnSetValue() { // Convert from generic wxobject ptr to wxPGVariantDataColour @@ -933,7 +1089,7 @@ void wxSystemColourProperty::OnSetValue() m_value = TranslateVal(val); } - int ind; + int ind = wxNOT_FOUND; if ( m_value.GetType() == wxS("wxColourPropertyValue") ) { @@ -941,19 +1097,17 @@ void wxSystemColourProperty::OnSetValue() cpv << m_value; wxColour col = cpv.m_colour; - if ( !col.Ok() ) + if ( !col.IsOk() ) { SetValueToUnspecified(); SetIndex(wxNOT_FOUND); return; } - if ( cpv.m_type < wxPG_COLOUR_WEB_BASE ) + if ( cpv.m_type < wxPG_COLOUR_WEB_BASE || + (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) { - if ( m_choices.HasValues() ) - ind = GetIndexForValue(cpv.m_type); - else - ind = ColToInd(col); + ind = GetIndexForValue(cpv.m_type); } else { @@ -966,7 +1120,7 @@ void wxSystemColourProperty::OnSetValue() wxColour col; col << m_value; - if ( !col.Ok() ) + if ( !col.IsOk() ) { SetValueToUnspecified(); SetIndex(wxNOT_FOUND); @@ -975,7 +1129,8 @@ void wxSystemColourProperty::OnSetValue() ind = ColToInd(col); - if ( ind == wxNOT_FOUND ) + if ( ind == wxNOT_FOUND && + !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) ind = GetCustomColourIndex(); } @@ -988,35 +1143,62 @@ wxColour wxSystemColourProperty::GetColour( int index ) const return wxSystemSettings::GetColour( (wxSystemColour)index ); } -wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const +wxString wxSystemColourProperty::ColourToString( const wxColour& col, + int index, + int argFlags ) const { + if ( index == wxNOT_FOUND ) - return wxString::Format(wxT("(%i,%i,%i)"), - (int)col.Red(), - (int)col.Green(), - (int)col.Blue()); + { + + if ( (argFlags & wxPG_FULL_VALUE) || + GetAttributeAsLong(wxPG_COLOUR_HAS_ALPHA, 0) ) + { + return wxString::Format(wxS("(%i,%i,%i,%i)"), + (int)col.Red(), + (int)col.Green(), + (int)col.Blue(), + (int)col.Alpha()); + } + else + { + return wxString::Format(wxS("(%i,%i,%i)"), + (int)col.Red(), + (int)col.Green(), + (int)col.Blue()); + } + } else + { return m_choices.GetLabel(index); + } } -wxString wxSystemColourProperty::GetValueAsString( int argFlags ) const +wxString wxSystemColourProperty::ValueToString( wxVariant& value, + int argFlags ) const { - wxColourPropertyValue val = GetVal(); + wxColourPropertyValue val = GetVal(&value); - int ind = GetIndex(); + int index; - // Always show custom colour for textctrl-editor - if ( val.m_type == wxPG_COLOUR_CUSTOM || - ind == GetCustomColourIndex() || - (argFlags & wxPG_PROPERTY_SPECIFIC) ) + if ( argFlags & wxPG_VALUE_IS_CURRENT ) { - return ColourToString(val.m_colour, wxNOT_FOUND); + // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set, + // but we should use it whenever possible. + index = GetIndex(); + + // If custom colour was selected, use invalid index, so that + // ColourToString() will return properly formatted colour text. + if ( index == GetCustomColourIndex() && + !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) + index = wxNOT_FOUND; + } + else + { + index = m_choices.Index(val.m_type); } - if ( ind == -1 ) - return wxEmptyString; - - return ColourToString(val.m_colour, ind); + return ColourToString(val.m_colour, index, argFlags); } @@ -1041,7 +1223,7 @@ bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const wxASSERT( propgrid ); // Must only occur when user triggers event - if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT) ) + if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) ) return res; wxColourPropertyValue val = GetVal(); @@ -1078,14 +1260,9 @@ bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const { int index = number; - int type = GetValueForIndex(index); - bool hasValue = m_choices[index].HasValue(); + int type = m_choices.GetValue(index); - if ( ( hasValue && type == wxPG_COLOUR_CUSTOM ) || - ( !hasValue && (index == (int)GetCustomColourIndex() && - !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR)) - ) - ) + if ( type == wxPG_COLOUR_CUSTOM ) { QueryColourFromUser(variant); } @@ -1098,12 +1275,37 @@ bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXU } // Need to do some extra event handling. -bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event ) +bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, + wxWindow* WXUNUSED(primary), + wxEvent& event ) { + bool askColour = false; + if ( propgrid->IsMainButtonEvent(event) ) { // We need to handle button click in case editor has been // switched to one that has wxButton as well. + askColour = true; + } + else if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED ) + { + // Must override index detection since at this point GetIndex() + // will return old value. + wxOwnerDrawnComboBox* cb = + static_cast(propgrid->GetEditorControl()); + + if ( cb ) + { + int index = cb->GetSelection(); + + if ( index == GetCustomColourIndex() && + !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) + askColour = true; + } + } + + if ( askColour && !propgrid->WasValueChangedInEvent() ) + { wxVariant variant; if ( QueryColourFromUser(variant) ) return true; @@ -1168,8 +1370,10 @@ void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, { wxColour col; - if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() && - paintdata.m_choiceItem != GetCustomColourIndex() ) + if ( paintdata.m_choiceItem >= 0 && + paintdata.m_choiceItem < (int)m_choices.GetCount() && + (paintdata.m_choiceItem != GetCustomColourIndex() || + m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) { int colInd = m_choices[paintdata.m_choiceItem].GetValue(); col = GetColour( colInd ); @@ -1179,7 +1383,7 @@ void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, col = GetVal().m_colour; } - if ( col.Ok() ) + if ( col.IsOk() ) { dc.SetBrush(col); dc.DrawRectangle(rect); @@ -1189,36 +1393,47 @@ void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const { - // - // Accept colour format "[Name] [(R,G,B)]" - // Name takes precedence. - // - wxString colourName; - wxString colourRGB; + wxString custColName(m_choices.GetLabel(GetCustomColourIndex())); + wxString colStr(text); + colStr.Trim(true); + colStr.Trim(false); - int ppos = text.Find(wxT("(")); + wxColour customColour; + bool conversionSuccess = false; - if ( ppos == wxNOT_FOUND ) - { - colourName = text; - } - else + if ( colStr != custColName ) { - colourName = text.substr(0, ppos); - colourRGB = text.substr(ppos, text.length()-ppos); - } + if ( colStr.Find(wxS("(")) == 0 ) + { + // Eliminate whitespace + colStr.Replace(wxS(" "), wxEmptyString); - // Strip spaces from extremities - colourName.Trim(true); - colourName.Trim(false); - colourRGB.Trim(true); + int commaCount = colStr.Freq(wxS(',')); + if ( commaCount == 2 ) + { + // Convert (R,G,B) to rgb(R,G,B) + colStr = wxS("rgb") + colStr; + } + else if ( commaCount == 3 ) + { + // We have int alpha, CSS format that wxColour takes as + // input processes float alpha. So, let's parse the colour + // ourselves instead of trying to convert it to a format + // that wxColour::FromString() understands. + int r = -1, g = -1, b = -1, a = -1; + wxSscanf(colStr, wxS("(%i,%i,%i,%i)"), &r, &g, &b, &a); + customColour.Set(r, g, b, a); + conversionSuccess = customColour.IsOk(); + } + } - // Validate colourRGB string - (1,1,1) is shortest allowed - if ( colourRGB.length() < 7 ) - colourRGB.clear(); + if ( !conversionSuccess ) + conversionSuccess = customColour.Set(colStr); + } - if ( colourRGB.length() == 0 && m_choices.GetCount() && - colourName == m_choices.GetLabel(GetCustomColourIndex()) ) + if ( !conversionSuccess && m_choices.GetCount() && + !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) && + colStr == custColName ) { if ( !(argFlags & wxPG_EDITABLE_VALUE )) { @@ -1236,14 +1451,16 @@ bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& te bool done = false; - if ( colourName.length() ) + if ( !conversionSuccess ) { // Try predefined colour first - bool res = wxEnumProperty::StringToValue(value, colourName, argFlags); + bool res = wxEnumProperty::StringToValue(value, + colStr, + argFlags); if ( res && GetIndex() >= 0 ) { val.m_type = GetIndex(); - if ( val.m_type >= 0 && val.m_type < m_choices.GetCount() && m_choices[val.m_type].HasValue() ) + if ( val.m_type < m_choices.GetCount() ) val.m_type = m_choices[val.m_type].GetValue(); // Get proper colour for type. @@ -1252,22 +1469,11 @@ bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& te done = true; } } - if ( colourRGB.length() && !done ) + else { - // Then check custom colour. val.m_type = wxPG_COLOUR_CUSTOM; - - int r = -1, g = -1, b = -1; - wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b); - - if ( r >= 0 && r <= 255 && - g >= 0 && g <= 255 && - b >= 0 && b <= 255 ) - { - val.m_colour.Set(r,g,b); - - done = true; - } + val.m_colour = customColour; + done = true; } if ( !done ) @@ -1287,9 +1493,7 @@ bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& va { if ( name == wxPG_COLOUR_ALLOW_CUSTOM ) { - int ival = wxPGVariantToInt(value); - - SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties + int ival = value.GetLong(); if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) { @@ -1313,7 +1517,7 @@ bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& va // wxColourProperty // ----------------------------------------------------------------------- -static const wxChar* gs_cp_es_normcolour_labels[] = { +static const wxChar* const gs_cp_es_normcolour_labels[] = { wxT("Black"), wxT("Maroon"), wxT("Navy"), @@ -1336,7 +1540,7 @@ static const wxChar* gs_cp_es_normcolour_labels[] = { (const wxChar*) NULL }; -static unsigned long gs_cp_es_normcolour_colours[] = { +static const unsigned long gs_cp_es_normcolour_colours[] = { wxPG_COLOUR(0,0,0), wxPG_COLOUR(128,0,0), wxPG_COLOUR(0,0,128), @@ -1381,7 +1585,7 @@ wxColourProperty::~wxColourProperty() void wxColourProperty::Init( wxColour colour ) { - if ( !colour.Ok() ) + if ( !colour.IsOk() ) colour = *wxWHITE; wxVariant variant; variant << colour; @@ -1392,7 +1596,8 @@ void wxColourProperty::Init( wxColour colour ) SetIndex( ind ); } -wxString wxColourProperty::GetValueAsString( int argFlags ) const +wxString wxColourProperty::ValueToString( wxVariant& value, + int argFlags ) const { const wxPGEditor* editor = GetEditorClass(); if ( editor != wxPGEditor_Choice && @@ -1400,16 +1605,11 @@ wxString wxColourProperty::GetValueAsString( int argFlags ) const editor != wxPGEditor_ComboBox ) argFlags |= wxPG_PROPERTY_SPECIFIC; - return wxSystemColourProperty::GetValueAsString(argFlags); + return wxSystemColourProperty::ValueToString(value, argFlags); } wxColour wxColourProperty::GetColour( int index ) const { - if ( !m_choices.HasValue(index) ) - { - wxASSERT( index < (int)GetItemCount() ); - return gs_cp_es_normcolour_colours[index]; - } return gs_cp_es_normcolour_colours[m_choices.GetValue(index)]; } @@ -1429,7 +1629,7 @@ wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const #define NUM_CURSORS 28 //#define wx_cp_es_syscursors_len 28 -static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = { +static const wxChar* const gs_cp_es_syscursors_labels[NUM_CURSORS+1] = { wxT("Default"), wxT("Arrow"), wxT("Right Arrow"), @@ -1461,7 +1661,7 @@ static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = { (const wxChar*) NULL }; -static long gs_cp_es_syscursors_values[NUM_CURSORS] = { +static const long gs_cp_es_syscursors_values[NUM_CURSORS] = { wxCURSOR_NONE, wxCURSOR_ARROW, wxCURSOR_RIGHT_ARROW, @@ -1554,7 +1754,10 @@ void wxCursorProperty::OnCustomPaint( wxDC& dc, 0, 0, NULL, - DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL + #if !defined(__WXWINCE__) + DI_COMPAT | DI_DEFAULTSIZE | + #endif + DI_NORMAL ); #endif } @@ -1579,7 +1782,7 @@ void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { } const wxString& wxPGGetDefaultImageWildcard() { // Form the wildcard, if not done yet - if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() ) + if ( wxPGGlobalVars->m_pDefaultImageWildcard.empty() ) { wxString str; @@ -1592,7 +1795,7 @@ const wxString& wxPGGetDefaultImageWildcard() // Let's iterate over the image handler list. //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() ) - for ( node = handlers.begin(); node != handlers.end(); node++ ) + for ( node = handlers.begin(); node != handlers.end(); ++node ) { wxImageHandler *handler = (wxImageHandler*)*node; @@ -1623,8 +1826,8 @@ wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& { SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() ); - m_pImage = (wxImage*) NULL; - m_pBitmap = (wxBitmap*) NULL; + m_pImage = NULL; + m_pBitmap = NULL; } wxImageFileProperty::~wxImageFileProperty() @@ -1640,21 +1843,15 @@ void wxImageFileProperty::OnSetValue() wxFileProperty::OnSetValue(); // Delete old image - if ( m_pImage ) - { - delete m_pImage; - m_pImage = NULL; - } - if ( m_pBitmap ) - { - delete m_pBitmap; - m_pBitmap = NULL; - } + wxDELETE(m_pImage); + wxDELETE(m_pBitmap); + + wxFileName filename = GetFileName(); // Create the image thumbnail - if ( m_filename.FileExists() ) + if ( filename.FileExists() ) { - m_pImage = new wxImage( m_filename.GetFullPath() ); + m_pImage = new wxImage( filename.GetFullPath() ); } } @@ -1667,7 +1864,7 @@ void wxImageFileProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& ) { - if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) ) + if ( m_pBitmap || (m_pImage && m_pImage->IsOk() ) ) { // Draw the thumbnail @@ -1676,8 +1873,7 @@ void wxImageFileProperty::OnCustomPaint( wxDC& dc, { m_pImage->Rescale( rect.width, rect.height ); m_pBitmap = new wxBitmap( *m_pImage ); - delete m_pImage; - m_pImage = NULL; + wxDELETE(m_pImage); } dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false ); @@ -1739,22 +1935,30 @@ wxMultiChoiceProperty::~wxMultiChoiceProperty() void wxMultiChoiceProperty::OnSetValue() { - GenerateValueAsString(); + GenerateValueAsString(m_value, &m_display); } -wxString wxMultiChoiceProperty::GetValueAsString( int ) const +wxString wxMultiChoiceProperty::ValueToString( wxVariant& value, + int argFlags ) const { - return m_display; + // If possible, use cached string + if ( argFlags & wxPG_VALUE_IS_CURRENT ) + return m_display; + + wxString s; + GenerateValueAsString(value, &s); + return s; } -void wxMultiChoiceProperty::GenerateValueAsString() +void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value, + wxString* target ) const { wxArrayString strings; - if ( m_value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING ) - strings = m_value.GetArrayString(); + if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING ) + strings = value.GetArrayString(); - wxString& tempStr = m_display; + wxString& tempStr = *target; unsigned int i; unsigned int itemCount = strings.size(); @@ -1774,7 +1978,8 @@ void wxMultiChoiceProperty::GenerateValueAsString() wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const { - const wxArrayInt& valueArr = wxArrayIntRefFromVariant(GetValue()); + wxVariant variant = GetValue(); + const wxArrayInt& valueArr = wxArrayIntRefFromVariant(variant); unsigned int i; // Translate values to string indices. @@ -1935,12 +2140,25 @@ wxDateProperty::~wxDateProperty() { } +void wxDateProperty::OnSetValue() +{ + // + // Convert invalid dates to unspecified value + if ( m_value.GetType() == wxT("datetime") ) + { + if ( !m_value.GetDateTime().IsValid() ) + m_value.MakeNull(); + } +} + bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const { wxDateTime dt; - const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL); + // FIXME: do we really want to return true from here if only part of the + // string was parsed? + const char* c = dt.ParseFormat(text); if ( c ) { @@ -1951,16 +2169,17 @@ bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text, return false; } -wxString wxDateProperty::GetValueAsString( int argFlags ) const +wxString wxDateProperty::ValueToString( wxVariant& value, + int argFlags ) const { const wxChar* format = (const wxChar*) NULL; - wxDateTime dateTime = m_value.GetDateTime(); + wxDateTime dateTime = value.GetDateTime(); if ( !dateTime.IsValid() ) return wxT("Invalid"); - if ( !ms_defaultDateFormat.length() ) + if ( ms_defaultDateFormat.empty() ) { #if wxUSE_DATEPICKCTRL bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false; @@ -1970,7 +2189,7 @@ wxString wxDateProperty::GetValueAsString( int argFlags ) const ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury ); } - if ( m_format.length() && + if ( !m_format.empty() && !(argFlags & wxPG_FULL_VALUE) ) format = m_format.c_str();