///////////////////////////////////////////////////////////////////////////// // Name: src/propgrid/advprops.cpp // Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.) // Author: Jaakko Salli // Modified by: // Created: 2004-09-25 // RCS-ID: $Id$ // Copyright: (c) Jaakko Salli // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #if wxUSE_PROPGRID #ifndef WX_PRECOMP #include "wx/defs.h" #include "wx/object.h" #include "wx/hash.h" #include "wx/string.h" #include "wx/log.h" #include "wx/event.h" #include "wx/window.h" #include "wx/panel.h" #include "wx/dc.h" #include "wx/dcclient.h" #include "wx/button.h" #include "wx/pen.h" #include "wx/brush.h" #include "wx/cursor.h" #include "wx/dialog.h" #include "wx/settings.h" #include "wx/msgdlg.h" #include "wx/choice.h" #include "wx/stattext.h" #include "wx/textctrl.h" #include "wx/scrolwin.h" #include "wx/dirdlg.h" #include "wx/combobox.h" #include "wx/sizer.h" #include "wx/textdlg.h" #include "wx/filedlg.h" #include "wx/intl.h" #include "wx/wxcrtvararg.h" #endif #define __wxPG_SOURCE_FILE__ #include "wx/propgrid/propgrid.h" #if wxPG_INCLUDE_ADVPROPS #include "wx/propgrid/advprops.h" #ifdef __WXMSW__ #include "wx/msw/private.h" #include "wx/msw/dc.h" #endif // ----------------------------------------------------------------------- #if defined(__WXMSW__) #define wxPG_CAN_DRAW_CURSOR 1 #elif defined(__WXGTK__) #define wxPG_CAN_DRAW_CURSOR 0 #elif defined(__WXMAC__) #define wxPG_CAN_DRAW_CURSOR 0 #else #define wxPG_CAN_DRAW_CURSOR 0 #endif // ----------------------------------------------------------------------- // Value type related // ----------------------------------------------------------------------- bool operator == (const wxFont&, const wxFont&) { return false; } // Implement dynamic class for type value. IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue, wxObject) bool operator == (const wxColourPropertyValue& a, const wxColourPropertyValue& b) { return ( ( a.m_colour == b.m_colour ) && (a.m_type == b.m_type) ); } bool operator == (const wxArrayInt& array1, const wxArrayInt& array2) { if ( array1.size() != array2.size() ) return false; size_t i; for ( i=0; iHide(); #endif wnd2->Create( propgrid->GetPanel(), wxPG_SUBID2, butPos, butSz, wxSP_VERTICAL ); 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 ); // 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 ); return wxPGWindowList(wnd1, wnd2); } // Control's events are redirected here bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* wnd, wxEvent& event ) const { int evtType = event.GetEventType(); int keycode = -1; bool bigStep = false; if ( evtType == wxEVT_KEY_DOWN ) { wxKeyEvent& keyEvent = (wxKeyEvent&)event; keycode = keyEvent.GetKeyCode(); if ( keycode == WXK_UP ) evtType = wxEVT_SCROLL_LINEUP; else if ( keycode == WXK_DOWN ) evtType = wxEVT_SCROLL_LINEDOWN; else if ( keycode == WXK_PAGEUP ) { evtType = wxEVT_SCROLL_LINEUP; bigStep = true; } else if ( keycode == WXK_PAGEDOWN ) { evtType = wxEVT_SCROLL_LINEDOWN; bigStep = true; } } if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN ) { wxString s; // Can't use wnd since it might be clipper window wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl); if ( tc ) s = tc->GetValue(); else s = property->GetValueAsString(wxPG_FULL_VALUE); int mode = wxPG_PROPERTY_VALIDATION_SATURATE; if ( property->GetAttributeAsLong(wxT("Wrap"), 0) ) mode = wxPG_PROPERTY_VALIDATION_WRAP; if ( property->GetValueType() == wxT("double") ) { double v_d; double step = property->GetAttributeAsDouble(wxT("Step"), 1.0); // Try double if ( s.ToDouble(&v_d) ) { if ( bigStep ) step *= 10.0; if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step; else v_d -= step; // Min/Max check wxFloatProperty::DoValidation(property, v_d, NULL, mode); wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL); } else { return false; } } else { wxLongLong_t v_ll; wxLongLong_t step = property->GetAttributeAsLong(wxT("Step"), 1); // Try (long) long if ( s.ToLongLong(&v_ll, 10) ) { if ( bigStep ) step *= 10; if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step; else v_ll -= step; // Min/Max check wxIntProperty::DoValidation(property, v_ll, NULL, mode); s = wxLongLong(v_ll).ToString(); } else { return false; } } if ( tc ) { int ip = tc->GetInsertionPoint(); int lp = tc->GetLastPosition(); tc->SetValue(s); tc->SetInsertionPoint(ip+(tc->GetLastPosition()-lp)); } return true; } return wxPGTextCtrlEditor::OnEvent(propgrid,property,wnd,event); } #endif // wxUSE_SPINBTN // ----------------------------------------------------------------------- // wxDatePickerCtrl-based property editor // ----------------------------------------------------------------------- #if wxUSE_DATEPICKCTRL #include "wx/datectrl.h" #include "wx/dateevt.h" class wxPGDatePickerCtrlEditor : public wxPGEditor { DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor) public: virtual ~wxPGDatePickerCtrlEditor(); wxString GetName() const; virtual wxPGWindowList CreateControls(wxPropertyGrid* propgrid, wxPGProperty* property, const wxPoint& pos, const wxSize& size) const; virtual void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const; virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, wxWindow* wnd, wxEvent& event ) const; virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* wnd ) const; virtual void SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const; }; WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl, wxPGDatePickerCtrlEditor, wxPGEditor) wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor() { } wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, const wxPoint& pos, const wxSize& sz ) const { wxCHECK_MSG( property->IsKindOf(CLASSINFO(wxDateProperty)), NULL, wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") ); wxDateProperty* prop = (wxDateProperty*) property; // Use two stage creation to allow cleaner display on wxMSW wxDatePickerCtrl* ctrl = new wxDatePickerCtrl(); #ifdef __WXMSW__ ctrl->Hide(); wxSize useSz = wxDefaultSize; useSz.x = sz.x; #else wxSize useSz = sz; #endif ctrl->Create(propgrid->GetPanel(), wxPG_SUBID1, prop->GetDateValue(), 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 return ctrl; } // Copies value from property to control 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() ); } // Control's events are redirected here bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid), wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(wnd), wxEvent& event ) const { if ( event.GetEventType() == wxEVT_DATE_CHANGED ) return true; return false; } bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const { wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd; wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) ); variant = ctrl->GetValue(); return true; } void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(wnd) ) const { // TODO? //wxDateProperty* prop = (wxDateProperty*) property; //ctrl->SetValue(?); } #endif // wxUSE_DATEPICKCTRL // ----------------------------------------------------------------------- // wxFontProperty // ----------------------------------------------------------------------- #include "wx/fontdlg.h" #include "wx/fontenum.h" static const wxChar* gs_fp_es_family_labels[] = { wxT("Default"), wxT("Decorative"), wxT("Roman"), wxT("Script"), wxT("Swiss"), wxT("Modern"), (const wxChar*) NULL }; static long gs_fp_es_family_values[] = { wxDEFAULT, wxDECORATIVE, wxROMAN, wxSCRIPT, wxSWISS, wxMODERN }; static const wxChar* gs_fp_es_style_labels[] = { wxT("Normal"), wxT("Slant"), wxT("Italic"), (const wxChar*) NULL }; static long gs_fp_es_style_values[] = { wxNORMAL, wxSLANT, wxITALIC }; static const wxChar* gs_fp_es_weight_labels[] = { wxT("Normal"), wxT("Light"), wxT("Bold"), (const wxChar*) NULL }; static long gs_fp_es_weight_values[] = { wxNORMAL, wxLIGHT, wxBOLD }; // Class body is in advprops.h WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty, wxFont,const wxFont&,TextCtrlAndButton) wxFontProperty::wxFontProperty( const wxString& label, const wxString& name, const wxFont& value ) : wxPGProperty(label,name) { SetValue(WXVARIANT(value)); // 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 faceNames.Sort(); wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames); } wxString emptyString(wxEmptyString); wxFont font; font << m_value; 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()) ); wxString faceName = font.GetFaceName(); // If font was not in there, add it now if ( faceName.length() && wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND ) wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName); wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxS("Face Name"), *wxPGGlobalVars->m_fontFamilyChoices); p->SetValueFromString(faceName, wxPG_FULL_VALUE); AddChild( p ); AddChild( 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()) ); AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"), font.GetUnderlined()) ); } wxFontProperty::~wxFontProperty() { } void wxFontProperty::OnSetValue() { wxFont font; font << m_value; if ( !font.Ok() ) { font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL); m_value << font; } } wxString wxFontProperty::GetValueAsString( int argFlags ) const { return wxPGProperty::GetValueAsString(argFlags); } bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event ) { if ( propgrid->IsMainButtonEvent(event) ) { // Update value from last minute changes PrepareValueForDialogEditing(propgrid); wxFontData data; wxFont font; font << m_value; data.SetInitialFont( font ); data.SetColour(*wxBLACK); wxFontDialog dlg(propgrid, data); if ( dlg.ShowModal() == wxID_OK ) { propgrid->EditorsValueWasModified(); wxVariant variant; variant << dlg.GetFontData().GetChosenFont(); SetValueInEvent( variant ); return true; } } return false; } void wxFontProperty::RefreshChildren() { if ( !GetChildCount() ) return; 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() ); } void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const { wxFont font; font << thisValue; if ( ind == 0 ) { font.SetPointSize( wxPGVariantToInt(childValue) ); } 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(); if ( faceIndex >= 0 ) faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex); font.SetFaceName( faceName ); } else if ( ind == 3 ) { int st = childValue.GetLong(); if ( st != wxFONTSTYLE_NORMAL && st != wxFONTSTYLE_SLANT && st != wxFONTSTYLE_ITALIC ) st = wxFONTWEIGHT_NORMAL; font.SetStyle( st ); } else if ( ind == 4 ) { int wt = childValue.GetLong(); if ( wt != wxFONTWEIGHT_NORMAL && wt != wxFONTWEIGHT_LIGHT && wt != wxFONTWEIGHT_BOLD ) wt = wxFONTWEIGHT_NORMAL; font.SetWeight( wt ); } else if ( ind == 5 ) { font.SetUnderlined( childValue.GetBool() ); } thisValue << font; } /* wxSize wxFontProperty::OnMeasureImage() const { return wxSize(-1,-1); } void wxFontProperty::OnCustomPaint(wxDC& dc, const wxRect& rect, wxPGPaintData& paintData) { wxString drawFace; if ( paintData.m_choiceItem >= 0 ) drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem); else drawFace = m_value_wxFont.GetFaceName(); if ( drawFace.length() ) { // Draw the background dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) ); //dc.SetBrush( *wxWHITE_BRUSH ); //dc.SetPen( *wxMEDIUM_GREY_PEN ); dc.DrawRectangle( rect ); wxFont oldFont = dc.GetFont(); wxFont drawFont(oldFont.GetPointSize(), wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace); dc.SetFont(drawFont); dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) ); dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 ); dc.SetFont(oldFont); } else { // No file - just draw a white box dc.SetBrush ( *wxWHITE_BRUSH ); dc.DrawRectangle ( rect ); } } */ // ----------------------------------------------------------------------- // wxSystemColourProperty // ----------------------------------------------------------------------- // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1 #define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2 #include "wx/colordlg.h" //#define wx_cp_es_syscolours_len 25 static const wxChar* gs_cp_es_syscolour_labels[] = { wxT("AppWorkspace"), wxT("ActiveBorder"), wxT("ActiveCaption"), wxT("ButtonFace"), wxT("ButtonHighlight"), wxT("ButtonShadow"), wxT("ButtonText"), wxT("CaptionText"), wxT("ControlDark"), wxT("ControlLight"), wxT("Desktop"), wxT("GrayText"), wxT("Highlight"), wxT("HighlightText"), wxT("InactiveBorder"), wxT("InactiveCaption"), wxT("InactiveCaptionText"), wxT("Menu"), wxT("Scrollbar"), wxT("Tooltip"), wxT("TooltipText"), wxT("Window"), wxT("WindowFrame"), wxT("WindowText"), wxT("Custom"), (const wxChar*) NULL }; static long gs_cp_es_syscolour_values[] = { wxSYS_COLOUR_APPWORKSPACE, wxSYS_COLOUR_ACTIVEBORDER, wxSYS_COLOUR_ACTIVECAPTION, wxSYS_COLOUR_BTNFACE, wxSYS_COLOUR_BTNHIGHLIGHT, wxSYS_COLOUR_BTNSHADOW, wxSYS_COLOUR_BTNTEXT , wxSYS_COLOUR_CAPTIONTEXT, wxSYS_COLOUR_3DDKSHADOW, wxSYS_COLOUR_3DLIGHT, wxSYS_COLOUR_BACKGROUND, wxSYS_COLOUR_GRAYTEXT, wxSYS_COLOUR_HIGHLIGHT, wxSYS_COLOUR_HIGHLIGHTTEXT, wxSYS_COLOUR_INACTIVEBORDER, wxSYS_COLOUR_INACTIVECAPTION, wxSYS_COLOUR_INACTIVECAPTIONTEXT, wxSYS_COLOUR_MENU, wxSYS_COLOUR_SCROLLBAR, wxSYS_COLOUR_INFOBK, wxSYS_COLOUR_INFOTEXT, wxSYS_COLOUR_WINDOW, wxSYS_COLOUR_WINDOWFRAME, wxSYS_COLOUR_WINDOWTEXT, wxPG_COLOUR_CUSTOM }; IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID) // Class body is in advprops.h WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty, wxColourPropertyValue,const wxColourPropertyValue&,Choice) void wxSystemColourProperty::Init( int type, const wxColour& colour ) { wxColourPropertyValue cpv; if ( colour.Ok() ) cpv.Init( type, colour ); else cpv.Init( type, *wxWHITE ); m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed. m_value << cpv; OnSetValue(); } static wxPGChoices gs_wxSystemColourProperty_choicesCache; wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name, const wxColourPropertyValue& value ) : wxEnumProperty( label, name, gs_cp_es_syscolour_labels, gs_cp_es_syscolour_values, &gs_wxSystemColourProperty_choicesCache ) { if ( &value ) Init( value.m_type, value.m_colour ); else Init( wxPG_COLOUR_CUSTOM, *wxWHITE ); } wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name, const wxChar** labels, const long* values, wxPGChoices* choicesCache, const wxColourPropertyValue& value ) : wxEnumProperty( label, name, labels, values, choicesCache ) { if ( &value ) Init( value.m_type, value.m_colour ); else Init( wxPG_COLOUR_CUSTOM, *wxWHITE ); } wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name, const wxChar** labels, const long* values, wxPGChoices* choicesCache, const wxColour& value ) : wxEnumProperty( label, name, labels, values, choicesCache ) { if ( &value ) Init( wxPG_COLOUR_CUSTOM, value ); else Init( wxPG_COLOUR_CUSTOM, *wxWHITE ); } wxSystemColourProperty::~wxSystemColourProperty() { } wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const { if ( !pVariant ) pVariant = &m_value; if ( pVariant->IsNull() ) return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour()); if ( pVariant->GetType() == wxS("wxColourPropertyValue") ) { wxColourPropertyValue v; v << *pVariant; return v; } wxColour col; bool variantProcessed = true; if ( pVariant->GetType() == wxS("wxColour*") ) { wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour); col = *pCol; } else if ( pVariant->GetType() == wxS("wxColour") ) { col << *pVariant; } else if ( pVariant->GetType() == wxArrayInt_VariantType ) { // This code is mostly needed for wxPython bindings, which // may offer tuple of integers as colour value. wxArrayInt arr; arr << *pVariant; if ( arr.size() >= 3 ) { int r, g, b; int a = 255; r = arr[0]; g = arr[1]; b = arr[2]; if ( arr.size() >= 4 ) a = arr[3]; col = wxColour(r, g, b, a); } else { variantProcessed = false; } } else { variantProcessed = false; } if ( !variantProcessed ) return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour()); wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col ); int colInd = ColToInd(col); if ( colInd != wxNOT_FOUND ) v2.m_type = colInd; return v2; } wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const { wxVariant variant; variant << v; return variant; } int wxSystemColourProperty::ColToInd( const wxColour& colour ) const { size_t i; size_t i_max = m_choices.GetCount() - 1; for ( i=0; i>8)&0xFF),((col>>16)&0xFF)); } void wxSystemColourProperty::OnSetValue() { // Convert from generic wxobject ptr to wxPGVariantDataColour if ( m_value.GetType() == wxS("wxColour*") ) { wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour); m_value << *pCol; } wxColourPropertyValue val = GetVal(&m_value); if ( val.m_type == wxPG_COLOUR_UNSPECIFIED ) { m_value.MakeNull(); return; } else { if ( val.m_type < wxPG_COLOUR_WEB_BASE ) val.m_colour = GetColour( val.m_type ); m_value = TranslateVal(val); } int ind; if ( m_value.GetType() == wxS("wxColourPropertyValue") ) { wxColourPropertyValue cpv; cpv << m_value; wxColour col = cpv.m_colour; if ( !col.Ok() ) { SetValueToUnspecified(); SetIndex(wxNOT_FOUND); return; } if ( cpv.m_type < wxPG_COLOUR_WEB_BASE ) { if ( m_choices.HasValues() ) ind = GetIndexForValue(cpv.m_type); else ind = ColToInd(col); } else { cpv.m_type = wxPG_COLOUR_CUSTOM; ind = GetCustomColourIndex(); } } else { wxColour col; col << m_value; if ( !col.Ok() ) { SetValueToUnspecified(); SetIndex(wxNOT_FOUND); return; } ind = ColToInd(col); if ( ind == wxNOT_FOUND ) ind = GetCustomColourIndex(); } SetIndex(ind); } wxColour wxSystemColourProperty::GetColour( int index ) const { return wxSystemSettings::GetColour( (wxSystemColour)index ); } wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const { if ( index == wxNOT_FOUND ) return wxString::Format(wxT("(%i,%i,%i)"), (int)col.Red(), (int)col.Green(), (int)col.Blue()); else return m_choices.GetLabel(index); } wxString wxSystemColourProperty::GetValueAsString( int argFlags ) const { wxColourPropertyValue val = GetVal(); int ind = GetIndex(); // Always show custom colour for textctrl-editor if ( val.m_type == wxPG_COLOUR_CUSTOM || ind == GetCustomColourIndex() || (argFlags & wxPG_PROPERTY_SPECIFIC) ) { return ColourToString(val.m_colour, wxNOT_FOUND); } if ( ind == -1 ) return wxEmptyString; return ColourToString(val.m_colour, ind); } wxSize wxSystemColourProperty::OnMeasureImage( int ) const { return wxPG_DEFAULT_IMAGE_SIZE; } int wxSystemColourProperty::GetCustomColourIndex() const { return m_choices.GetCount() - 1; } bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const { wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING ); bool res = false; wxPropertyGrid* propgrid = GetGrid(); wxASSERT( propgrid ); // Must only occur when user triggers event if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT) ) return res; wxColourPropertyValue val = GetVal(); val.m_type = wxPG_COLOUR_CUSTOM; wxColourData data; data.SetChooseFull(true); data.SetColour(val.m_colour); int i; for ( i = 0; i < 16; i++) { wxColour colour(i*16, i*16, i*16); data.SetCustomColour(i, colour); } wxColourDialog dialog(propgrid, &data); if ( dialog.ShowModal() == wxID_OK ) { wxColourData retData = dialog.GetColourData(); val.m_colour = retData.GetColour(); variant = DoTranslateVal(val); SetValueInEvent(variant); res = true; } return res; } bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const { int index = number; int type = GetValueForIndex(index); bool hasValue = m_choices[index].HasValue(); if ( ( hasValue && type == wxPG_COLOUR_CUSTOM ) || ( !hasValue && (index == (int)GetCustomColourIndex() && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR)) ) ) { QueryColourFromUser(variant); } else { variant = TranslateVal( type, GetColour(type) ); } return true; } // Need to do some extra event handling. bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event ) { if ( propgrid->IsMainButtonEvent(event) ) { // We need to handle button click in case editor has been // switched to one that has wxButton as well. wxVariant variant; if ( QueryColourFromUser(variant) ) return true; } return false; } /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer { public: virtual void Render( wxDC& dc, const wxRect& rect, const wxPropertyGrid* propertyGrid, wxPGProperty* property, int WXUNUSED(column), int item, int WXUNUSED(flags) ) const { wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) ); wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty); dc.SetPen(*wxBLACK_PEN); if ( item >= 0 && ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR))) ) { int colInd; const wxArrayInt& values = prop->GetValues(); if ( values.GetChildCount() ) colInd = values[item]; else colInd = item; dc.SetBrush( wxColour( prop->GetColour( colInd ) ) ); } else if ( !prop->IsValueUnspecified() ) dc.SetBrush( prop->GetVal().m_colour ); else dc.SetBrush( *wxWHITE ); wxRect imageRect = propertyGrid->GetImageRect(property, item); wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y); dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y, imageRect.width, imageRect.height ); wxString text; if ( item == -1 ) text = property->GetValueAsString(); else text = property->GetChoiceString(item); DrawText( dc, rect, imageRect.width, text ); } protected: }; wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer; wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const { if ( column == 1 ) return &g_wxPGColourPropertyRenderer; return wxEnumProperty::GetCellRenderer(column); }*/ void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& paintdata ) { wxColour col; if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() && paintdata.m_choiceItem != GetCustomColourIndex() ) { int colInd = m_choices[paintdata.m_choiceItem].GetValue(); col = GetColour( colInd ); } else if ( !IsValueUnspecified() ) { col = GetVal().m_colour; } if ( col.Ok() ) { dc.SetBrush(col); dc.DrawRectangle(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; int ppos = text.Find(wxT("(")); if ( ppos == wxNOT_FOUND ) { colourName = text; } else { colourName = text.substr(0, ppos); colourRGB = text.substr(ppos, text.length()-ppos); } // Strip spaces from extremities colourName.Trim(true); colourName.Trim(false); colourRGB.Trim(true); // Validate colourRGB string - (1,1,1) is shortest allowed if ( colourRGB.length() < 7 ) colourRGB.clear(); if ( colourRGB.length() == 0 && m_choices.GetCount() && colourName == m_choices.GetLabel(GetCustomColourIndex()) ) { if ( !(argFlags & wxPG_EDITABLE_VALUE )) { // This really should not occurr... // wxASSERT(false); ResetNextIndex(); return false; } QueryColourFromUser(value); } else { wxColourPropertyValue val; bool done = false; if ( colourName.length() ) { // Try predefined colour first bool res = wxEnumProperty::StringToValue(value, colourName, 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() ) val.m_type = m_choices[val.m_type].GetValue(); // Get proper colour for type. val.m_colour = GetColour(val.m_type); done = true; } } if ( colourRGB.length() && !done ) { // 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; } } if ( !done ) { ResetNextIndex(); return false; } value = DoTranslateVal(val); } return true; } bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value ) { if ( name == wxPG_COLOUR_ALLOW_CUSTOM ) { int ival = wxPGVariantToInt(value); SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) { // Show custom choice m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM); m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR); } else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) { // Hide custom choice m_choices.RemoveAt(GetCustomColourIndex()); m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR; } return true; } return false; } // ----------------------------------------------------------------------- // wxColourProperty // ----------------------------------------------------------------------- static const wxChar* gs_cp_es_normcolour_labels[] = { wxT("Black"), wxT("Maroon"), wxT("Navy"), wxT("Purple"), wxT("Teal"), wxT("Gray"), wxT("Green"), wxT("Olive"), wxT("Brown"), wxT("Blue"), wxT("Fuchsia"), wxT("Red"), wxT("Orange"), wxT("Silver"), wxT("Lime"), wxT("Aqua"), wxT("Yellow"), wxT("White"), wxT("Custom"), (const wxChar*) NULL }; static unsigned long gs_cp_es_normcolour_colours[] = { wxPG_COLOUR(0,0,0), wxPG_COLOUR(128,0,0), wxPG_COLOUR(0,0,128), wxPG_COLOUR(128,0,128), wxPG_COLOUR(0,128,128), wxPG_COLOUR(128,128,128), wxPG_COLOUR(0,128,0), wxPG_COLOUR(128,128,0), wxPG_COLOUR(166,124,81), wxPG_COLOUR(0,0,255), wxPG_COLOUR(255,0,255), wxPG_COLOUR(255,0,0), wxPG_COLOUR(247,148,28), wxPG_COLOUR(192,192,192), wxPG_COLOUR(0,255,0), wxPG_COLOUR(0,255,255), wxPG_COLOUR(255,255,0), wxPG_COLOUR(255,255,255), wxPG_COLOUR(0,0,0) }; WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty, wxColour, const wxColour&, TextCtrlAndButton) static wxPGChoices gs_wxColourProperty_choicesCache; wxColourProperty::wxColourProperty( const wxString& label, const wxString& name, const wxColour& value ) : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels, NULL, &gs_wxColourProperty_choicesCache, value ) { Init( value ); m_flags |= wxPG_PROP_TRANSLATE_CUSTOM; } wxColourProperty::~wxColourProperty() { } void wxColourProperty::Init( wxColour colour ) { if ( !colour.Ok() ) colour = *wxWHITE; wxVariant variant; variant << colour; m_value = variant; int ind = ColToInd(colour); if ( ind < 0 ) ind = m_choices.GetCount() - 1; SetIndex( ind ); } wxString wxColourProperty::GetValueAsString( int argFlags ) const { const wxPGEditor* editor = GetEditorClass(); if ( editor != wxPGEditor_Choice && editor != wxPGEditor_ChoiceAndButton && editor != wxPGEditor_ComboBox ) argFlags |= wxPG_PROPERTY_SPECIFIC; return wxSystemColourProperty::GetValueAsString(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)]; } wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const { wxVariant variant; variant << v.m_colour; return variant; } // ----------------------------------------------------------------------- // wxCursorProperty // ----------------------------------------------------------------------- #define wxPG_CURSOR_IMAGE_WIDTH 32 #define NUM_CURSORS 28 //#define wx_cp_es_syscursors_len 28 static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = { wxT("Default"), wxT("Arrow"), wxT("Right Arrow"), wxT("Blank"), wxT("Bullseye"), wxT("Character"), wxT("Cross"), wxT("Hand"), wxT("I-Beam"), wxT("Left Button"), wxT("Magnifier"), wxT("Middle Button"), wxT("No Entry"), wxT("Paint Brush"), wxT("Pencil"), wxT("Point Left"), wxT("Point Right"), wxT("Question Arrow"), wxT("Right Button"), wxT("Sizing NE-SW"), wxT("Sizing N-S"), wxT("Sizing NW-SE"), wxT("Sizing W-E"), wxT("Sizing"), wxT("Spraycan"), wxT("Wait"), wxT("Watch"), wxT("Wait Arrow"), (const wxChar*) NULL }; static long gs_cp_es_syscursors_values[NUM_CURSORS] = { wxCURSOR_NONE, wxCURSOR_ARROW, wxCURSOR_RIGHT_ARROW, wxCURSOR_BLANK, wxCURSOR_BULLSEYE, wxCURSOR_CHAR, wxCURSOR_CROSS, wxCURSOR_HAND, wxCURSOR_IBEAM, wxCURSOR_LEFT_BUTTON, wxCURSOR_MAGNIFIER, wxCURSOR_MIDDLE_BUTTON, wxCURSOR_NO_ENTRY, wxCURSOR_PAINT_BRUSH, wxCURSOR_PENCIL, wxCURSOR_POINT_LEFT, wxCURSOR_POINT_RIGHT, wxCURSOR_QUESTION_ARROW, wxCURSOR_RIGHT_BUTTON, wxCURSOR_SIZENESW, wxCURSOR_SIZENS, wxCURSOR_SIZENWSE, wxCURSOR_SIZEWE, wxCURSOR_SIZING, wxCURSOR_SPRAYCAN, wxCURSOR_WAIT, wxCURSOR_WATCH, wxCURSOR_ARROWWAIT }; IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty) wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name, int value ) : wxEnumProperty( label, name, gs_cp_es_syscursors_labels, gs_cp_es_syscursors_values, value ) { m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed. } wxCursorProperty::~wxCursorProperty() { } wxSize wxCursorProperty::OnMeasureImage( int item ) const { #if wxPG_CAN_DRAW_CURSOR if ( item != -1 && item < NUM_CURSORS ) return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH); #else wxUnusedVar(item); #endif return wxSize(0,0); } #if wxPG_CAN_DRAW_CURSOR void wxCursorProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& paintdata ) { // Background brush dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); if ( paintdata.m_choiceItem >= 0 ) { dc.DrawRectangle( rect ); if ( paintdata.m_choiceItem < NUM_CURSORS ) { wxStockCursor cursorIndex = (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem]; { if ( cursorIndex == wxCURSOR_NONE ) cursorIndex = wxCURSOR_ARROW; wxCursor cursor( cursorIndex ); #ifdef __WXMSW__ HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC(); ::DrawIconEx( hDc, rect.x, rect.y, (HICON)cursor.GetHandle(), 0, 0, 0, NULL, DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL ); #endif } } } } #else void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { } /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const { return wxEnumProperty::GetCellRenderer(column); }*/ #endif // ----------------------------------------------------------------------- // wxImageFileProperty // ----------------------------------------------------------------------- #if wxUSE_IMAGE const wxString& wxPGGetDefaultImageWildcard() { // Form the wildcard, if not done yet if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() ) { wxString str; // TODO: This section may require locking (using global). wxList& handlers = wxImage::GetHandlers(); wxList::iterator node; // 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++ ) { wxImageHandler *handler = (wxImageHandler*)*node; wxString ext_lo = handler->GetExtension(); wxString ext_up = ext_lo.Upper(); str.append( ext_up ); str.append( wxT(" files (*.") ); str.append( ext_up ); str.append( wxT(")|*.") ); str.append( ext_lo ); str.append( wxT("|") ); } str.append ( wxT("All files (*.*)|*.*") ); wxPGGlobalVars->m_pDefaultImageWildcard = str; } return wxPGGlobalVars->m_pDefaultImageWildcard; } IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty) wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name, const wxString& value ) : wxFileProperty(label,name,value) { SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() ); m_pImage = (wxImage*) NULL; m_pBitmap = (wxBitmap*) NULL; } wxImageFileProperty::~wxImageFileProperty() { if ( m_pBitmap ) delete m_pBitmap; if ( m_pImage ) delete m_pImage; } 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; } // Create the image thumbnail if ( m_filename.FileExists() ) { m_pImage = new wxImage( m_filename.GetFullPath() ); } } wxSize wxImageFileProperty::OnMeasureImage( int ) const { return wxPG_DEFAULT_IMAGE_SIZE; } void wxImageFileProperty::OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& ) { if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) ) { // Draw the thumbnail // Create the bitmap here because required size is not known in OnSetValue(). if ( !m_pBitmap ) { m_pImage->Rescale( rect.width, rect.height ); m_pBitmap = new wxBitmap( *m_pImage ); delete m_pImage; m_pImage = NULL; } dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false ); } else { // No file - just draw a white box dc.SetBrush( *wxWHITE_BRUSH ); dc.DrawRectangle ( rect ); } } #endif // wxUSE_IMAGE // ----------------------------------------------------------------------- // wxMultiChoiceProperty // ----------------------------------------------------------------------- #if wxUSE_CHOICEDLG #include "wx/choicdlg.h" WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty, wxArrayInt,const wxArrayInt&,TextCtrlAndButton) wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label, const wxString& name, const wxPGChoices& choices, const wxArrayString& value) : wxPGProperty(label,name) { m_choices.Assign(choices); SetValue(value); } wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label, const wxString& name, const wxArrayString& strings, const wxArrayString& value) : wxPGProperty(label,name) { m_choices.Set(strings); SetValue(value); } wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label, const wxString& name, const wxArrayString& value) : wxPGProperty(label,name) { wxArrayString strings; m_choices.Set(strings); SetValue(value); } wxMultiChoiceProperty::~wxMultiChoiceProperty() { } void wxMultiChoiceProperty::OnSetValue() { GenerateValueAsString(); } wxString wxMultiChoiceProperty::GetValueAsString( int ) const { return m_display; } void wxMultiChoiceProperty::GenerateValueAsString() { wxArrayString strings; if ( m_value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING ) strings = m_value.GetArrayString(); wxString& tempStr = m_display; unsigned int i; unsigned int itemCount = strings.size(); tempStr.Empty(); if ( itemCount ) tempStr.append( wxT("\"") ); for ( i = 0; i < itemCount; i++ ) { tempStr.append( strings[i] ); tempStr.append( wxT("\"") ); if ( i < (itemCount-1) ) tempStr.append ( wxT(" \"") ); } } wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const { const wxArrayInt& valueArr = wxArrayIntRefFromVariant(GetValue()); unsigned int i; // Translate values to string indices. wxArrayInt selections; if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) ) { for ( i=0; i= 0 ) selections.Add(sIndex); } } return selections; } bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event ) { if ( propgrid->IsMainButtonEvent(event) ) { // Update the value PrepareValueForDialogEditing(propgrid); wxArrayString labels = m_choices.GetLabels(); unsigned int choiceCount; if ( m_choices.IsOk() ) choiceCount = m_choices.GetCount(); else choiceCount = 0; // launch editor dialog wxMultiChoiceDialog dlg( propgrid, _("Make a selection:"), m_label, choiceCount, choiceCount?&labels[0]:NULL, wxCHOICEDLG_STYLE ); dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) ); wxArrayString strings = m_value.GetArrayString(); wxArrayString extraStrings; dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings)); if ( dlg.ShowModal() == wxID_OK && choiceCount ) { int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0); wxArrayInt arrInt = dlg.GetSelections(); wxVariant variant; // Strings that were not in list of choices wxArrayString value; // Translate string indices to strings unsigned int n; if ( userStringMode == 1 ) { for (n=0;n 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) ) arr.Add(token); WX_PG_TOKENIZER2_END() wxVariant v( WXVARIANT(arr) ); variant = v; return true; } #endif // wxUSE_CHOICEDLG // ----------------------------------------------------------------------- // wxDateProperty // ----------------------------------------------------------------------- #if wxUSE_DATETIME #if wxUSE_DATEPICKCTRL #define dtCtrl DatePickerCtrl #else #define dtCtrl TextCtrl #endif WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty, wxPGProperty, wxDateTime, const wxDateTime&, dtCtrl) wxString wxDateProperty::ms_defaultDateFormat; wxDateProperty::wxDateProperty( const wxString& label, const wxString& name, const wxDateTime& value ) : wxPGProperty(label,name) { //wxPGRegisterDefaultValueType(wxDateTime) #if wxUSE_DATEPICKCTRL wxPGRegisterEditorClass(DatePickerCtrl); m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY; #else m_dpStyle = 0; #endif SetValue( value ); } wxDateProperty::~wxDateProperty() { } bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text, int WXUNUSED(argFlags) ) const { wxDateTime dt; const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL); if ( c ) { variant = dt; return true; } return false; } wxString wxDateProperty::GetValueAsString( int argFlags ) const { const wxChar* format = (const wxChar*) NULL; wxDateTime dateTime = m_value.GetDateTime(); if ( !dateTime.IsValid() ) return wxT("Invalid"); if ( !ms_defaultDateFormat.length() ) { #if wxUSE_DATEPICKCTRL bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false; #else bool showCentury = true; #endif ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury ); } if ( m_format.length() && !(argFlags & wxPG_FULL_VALUE) ) format = m_format.c_str(); // Determine default from locale // NB: This is really simple stuff, but can't figure anything // better without proper support in wxLocale if ( !format ) format = ms_defaultDateFormat.c_str(); return dateTime.Format(format); } wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury ) { // This code is basicly copied from datectlg.cpp's SetFormat // wxString format; wxDateTime dt; dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d")); wxString str(dt.Format(wxT("%x"))); const wxChar *p = str.c_str(); while ( *p ) { int n=wxAtoi(p); if (n == dt.GetDay()) { format.Append(wxT("%d")); p += 2; } else if (n == (int)dt.GetMonth()+1) { format.Append(wxT("%m")); p += 2; } else if (n == dt.GetYear()) { format.Append(wxT("%Y")); p += 4; } else if (n == (dt.GetYear() % 100)) { if (showCentury) format.Append(wxT("%Y")); else format.Append(wxT("%y")); p += 2; } else format.Append(*p++); } return format; } bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value ) { if ( name == wxPG_DATE_FORMAT ) { m_format = value.GetString(); return true; } else if ( name == wxPG_DATE_PICKER_STYLE ) { m_dpStyle = value.GetLong(); ms_defaultDateFormat.clear(); // This may need recalculation return true; } return false; } #endif // wxUSE_DATETIME // ----------------------------------------------------------------------- // wxPropertyGridInterface // ----------------------------------------------------------------------- void wxPropertyGridInterface::InitAllTypeHandlers() { } // ----------------------------------------------------------------------- void wxPropertyGridInterface::RegisterAdditionalEditors() { // Register editor classes, if necessary. if ( wxPGGlobalVars->m_mapEditorClasses.empty() ) wxPropertyGrid::RegisterDefaultEditors(); #if wxUSE_SPINBTN wxPGRegisterEditorClass(SpinCtrl); #endif #if wxUSE_DATEPICKCTRL wxPGRegisterEditorClass(DatePickerCtrl); #endif } // ----------------------------------------------------------------------- #endif // wxPG_INCLUDE_ADVPROPS #endif // wxUSE_PROPGRID