1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/advprops.cpp
3 // Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.)
4 // Author: Jaakko Salli
7 // Copyright: (c) Jaakko Salli
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
22 #include "wx/object.h"
24 #include "wx/string.h"
27 #include "wx/window.h"
30 #include "wx/dcclient.h"
31 #include "wx/button.h"
34 #include "wx/cursor.h"
35 #include "wx/dialog.h"
36 #include "wx/settings.h"
37 #include "wx/msgdlg.h"
38 #include "wx/choice.h"
39 #include "wx/stattext.h"
40 #include "wx/textctrl.h"
41 #include "wx/scrolwin.h"
42 #include "wx/dirdlg.h"
43 #include "wx/combobox.h"
45 #include "wx/textdlg.h"
46 #include "wx/filedlg.h"
48 #include "wx/wxcrtvararg.h"
51 #define __wxPG_SOURCE_FILE__
53 #include "wx/propgrid/propgrid.h"
55 #if wxPG_INCLUDE_ADVPROPS
57 #include "wx/propgrid/advprops.h"
60 #include "wx/msw/private.h"
61 #include "wx/msw/dc.h"
64 #include "wx/odcombo.h"
66 // -----------------------------------------------------------------------
68 #if defined(__WXMSW__)
69 #define wxPG_CAN_DRAW_CURSOR 1
70 #elif defined(__WXGTK__)
71 #define wxPG_CAN_DRAW_CURSOR 0
72 #elif defined(__WXMAC__)
73 #define wxPG_CAN_DRAW_CURSOR 0
75 #define wxPG_CAN_DRAW_CURSOR 0
79 // -----------------------------------------------------------------------
81 // -----------------------------------------------------------------------
84 // Implement dynamic class for type value.
85 IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue
, wxObject
)
87 bool operator == (const wxColourPropertyValue
& a
, const wxColourPropertyValue
& b
)
89 return ( ( a
.m_colour
== b
.m_colour
) && (a
.m_type
== b
.m_type
) );
92 bool operator == (const wxArrayInt
& array1
, const wxArrayInt
& array2
)
94 if ( array1
.size() != array2
.size() )
97 for ( i
=0; i
<array1
.size(); i
++ )
99 if ( array1
[i
] != array2
[i
] )
105 // -----------------------------------------------------------------------
106 // wxSpinCtrl-based property editor
107 // -----------------------------------------------------------------------
113 #define IS_MOTION_SPIN_SUPPORTED 1
115 #define IS_MOTION_SPIN_SUPPORTED 0
118 #if IS_MOTION_SPIN_SUPPORTED
121 // This class implements ability to rapidly change "spin" value
122 // by moving mouse when one of the spin buttons is depressed.
123 class wxPGSpinButton
: public wxSpinButton
126 wxPGSpinButton() : wxSpinButton()
129 m_hasCapture
= false;
132 Connect( wxEVT_LEFT_DOWN
,
133 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
134 Connect( wxEVT_LEFT_UP
,
135 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
136 Connect( wxEVT_MOTION
,
137 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
138 Connect( wxEVT_MOUSE_CAPTURE_LOST
,
139 wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost
) );
148 wxPoint m_ptPosition
;
150 // Having a separate spins variable allows us to handle validation etc. for
151 // multiple spin events at once (with quick mouse movements there could be
152 // hundreds of 'spins' being done at once). Technically things like this
153 // should be stored in event (wxSpinEvent in this case), but there probably
154 // isn't anything there that can be reliably reused.
159 // SpinButton seems to be a special for mouse capture, so we may need track
160 // privately whether mouse is actually captured.
171 SetCursor(wxCURSOR_SIZENS
);
180 m_hasCapture
= false;
183 wxWindow
*parent
= GetParent();
185 SetCursor(parent
->GetCursor());
187 SetCursor(wxNullCursor
);
190 void OnMouseEvent(wxMouseEvent
& event
)
192 if ( event
.GetEventType() == wxEVT_LEFT_DOWN
)
195 m_ptPosition
= event
.GetPosition();
197 else if ( event
.GetEventType() == wxEVT_LEFT_UP
)
202 else if ( event
.GetEventType() == wxEVT_MOTION
)
206 int dy
= m_ptPosition
.y
- event
.GetPosition().y
;
210 m_ptPosition
= event
.GetPosition();
212 wxSpinEvent
evtscroll( (dy
>= 0) ? wxEVT_SCROLL_LINEUP
:
213 wxEVT_SCROLL_LINEDOWN
,
215 evtscroll
.SetEventObject(this);
217 wxASSERT( m_spins
== 1 );
220 GetEventHandler()->ProcessEvent(evtscroll
);
228 void OnMouseCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
))
234 #endif // IS_MOTION_SPIN_SUPPORTED
237 WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl
,
242 // Destructor. It is useful to reset the global pointer in it.
243 wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
245 wxPG_EDITOR(SpinCtrl
) = NULL
;
248 // Create controls and initialize event handling.
249 wxPGWindowList
wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
250 const wxPoint
& pos
, const wxSize
& sz
) const
252 const int margin
= 1;
253 wxSize
butSz(18, sz
.y
);
254 wxSize
tcSz(sz
.x
- butSz
.x
- margin
, sz
.y
);
255 wxPoint
butPos(pos
.x
+ tcSz
.x
+ margin
, pos
.y
);
259 #if IS_MOTION_SPIN_SUPPORTED
260 if ( property
->GetAttributeAsLong(wxT("MotionSpin"), 0) )
262 wnd2
= new wxPGSpinButton();
267 wnd2
= new wxSpinButton();
273 wnd2
->Create( propgrid
->GetPanel(), wxPG_SUBID2
, butPos
, butSz
, wxSP_VERTICAL
);
275 wnd2
->SetRange( INT_MIN
, INT_MAX
);
278 wxWindow
* wnd1
= wxPGTextCtrlEditor::CreateControls(propgrid
, property
, pos
, tcSz
).m_primary
;
280 // Let's add validator to make sure only numbers can be entered
281 wxTextValidator
validator(wxFILTER_NUMERIC
, &m_tempString
);
282 wnd1
->SetValidator(validator
);
285 return wxPGWindowList(wnd1
, wnd2
);
288 // Control's events are redirected here
289 bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
290 wxWindow
* wnd
, wxEvent
& event
) const
292 int evtType
= event
.GetEventType();
295 bool bigStep
= false;
297 if ( evtType
== wxEVT_KEY_DOWN
)
299 wxKeyEvent
& keyEvent
= (wxKeyEvent
&)event
;
300 keycode
= keyEvent
.GetKeyCode();
302 if ( keycode
== WXK_UP
)
303 evtType
= wxEVT_SCROLL_LINEUP
;
304 else if ( keycode
== WXK_DOWN
)
305 evtType
= wxEVT_SCROLL_LINEDOWN
;
306 else if ( keycode
== WXK_PAGEUP
)
308 evtType
= wxEVT_SCROLL_LINEUP
;
311 else if ( keycode
== WXK_PAGEDOWN
)
313 evtType
= wxEVT_SCROLL_LINEDOWN
;
318 if ( evtType
== wxEVT_SCROLL_LINEUP
|| evtType
== wxEVT_SCROLL_LINEDOWN
)
320 #if IS_MOTION_SPIN_SUPPORTED
321 if ( property
->GetAttributeAsLong(wxT("MotionSpin"), 0) )
323 wxPGSpinButton
* spinButton
=
324 (wxPGSpinButton
*) propgrid
->GetEditorControlSecondary();
327 spins
= spinButton
->GetSpins();
332 // Can't use wnd since it might be clipper window
333 wxTextCtrl
* tc
= wxDynamicCast(propgrid
->GetEditorControl(), wxTextCtrl
);
338 s
= property
->GetValueAsString(wxPG_FULL_VALUE
);
340 int mode
= wxPG_PROPERTY_VALIDATION_SATURATE
;
342 if ( property
->GetAttributeAsLong(wxT("Wrap"), 0) )
343 mode
= wxPG_PROPERTY_VALIDATION_WRAP
;
345 if ( property
->GetValueType() == wxT("double") )
348 double step
= property
->GetAttributeAsDouble(wxT("Step"), 1.0);
351 if ( s
.ToDouble(&v_d
) )
356 step
*= (double) spins
;
358 if ( evtType
== wxEVT_SCROLL_LINEUP
) v_d
+= step
;
362 wxFloatProperty::DoValidation(property
, v_d
, NULL
, mode
);
364 wxPropertyGrid::DoubleToString(s
, v_d
, 6, true, NULL
);
374 wxLongLong_t step
= property
->GetAttributeAsLong(wxT("Step"), 1);
377 if ( s
.ToLongLong(&v_ll
, 10) )
384 if ( evtType
== wxEVT_SCROLL_LINEUP
) v_ll
+= step
;
388 wxIntProperty::DoValidation(property
, v_ll
, NULL
, mode
);
390 s
= wxLongLong(v_ll
).ToString();
400 int ip
= tc
->GetInsertionPoint();
401 int lp
= tc
->GetLastPosition();
403 tc
->SetInsertionPoint(ip
+(tc
->GetLastPosition()-lp
));
409 return wxPGTextCtrlEditor::OnEvent(propgrid
,property
,wnd
,event
);
412 #endif // wxUSE_SPINBTN
415 // -----------------------------------------------------------------------
416 // wxDatePickerCtrl-based property editor
417 // -----------------------------------------------------------------------
419 #if wxUSE_DATEPICKCTRL
422 #include "wx/datectrl.h"
423 #include "wx/dateevt.h"
425 class wxPGDatePickerCtrlEditor
: public wxPGEditor
427 DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor
)
429 virtual ~wxPGDatePickerCtrlEditor();
431 wxString
GetName() const;
432 virtual wxPGWindowList
CreateControls(wxPropertyGrid
* propgrid
,
433 wxPGProperty
* property
,
435 const wxSize
& size
) const;
436 virtual void UpdateControl( wxPGProperty
* property
, wxWindow
* wnd
) const;
437 virtual bool OnEvent( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
438 wxWindow
* wnd
, wxEvent
& event
) const;
439 virtual bool GetValueFromControl( wxVariant
& variant
, wxPGProperty
* property
, wxWindow
* wnd
) const;
440 virtual void SetValueToUnspecified( wxPGProperty
* WXUNUSED(property
), wxWindow
* wnd
) const;
444 WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl
,
445 wxPGDatePickerCtrlEditor
,
449 wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
451 wxPG_EDITOR(DatePickerCtrl
) = NULL
;
454 wxPGWindowList
wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid
* propgrid
,
455 wxPGProperty
* property
,
457 const wxSize
& sz
) const
459 wxCHECK_MSG( wxDynamicCast(property
, wxDateProperty
),
461 wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
463 wxDateProperty
* prop
= wxDynamicCast(property
, wxDateProperty
);
465 // Use two stage creation to allow cleaner display on wxMSW
466 wxDatePickerCtrl
* ctrl
= new wxDatePickerCtrl();
469 wxSize useSz
= wxDefaultSize
;
475 wxDateTime
dateValue(wxInvalidDateTime
);
477 wxVariant value
= prop
->GetValue();
478 if ( value
.GetType() == wxT("datetime") )
479 dateValue
= value
.GetDateTime();
481 ctrl
->Create(propgrid
->GetPanel(),
486 prop
->GetDatePickerStyle() | wxNO_BORDER
);
495 // Copies value from property to control
496 void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty
* property
,
497 wxWindow
* wnd
) const
499 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
500 wxASSERT( wxDynamicCast(ctrl
, wxDatePickerCtrl
) );
502 wxDateTime
dateValue(wxInvalidDateTime
);
503 wxVariant
v(property
->GetValue());
504 if ( v
.GetType() == wxT("datetime") )
505 dateValue
= v
.GetDateTime();
507 ctrl
->SetValue( dateValue
);
510 // Control's events are redirected here
511 bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid
* WXUNUSED(propgrid
),
512 wxPGProperty
* WXUNUSED(property
),
513 wxWindow
* WXUNUSED(wnd
),
514 wxEvent
& event
) const
516 if ( event
.GetEventType() == wxEVT_DATE_CHANGED
)
522 bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant
& variant
, wxPGProperty
* WXUNUSED(property
), wxWindow
* wnd
) const
524 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
525 wxASSERT( wxDynamicCast(ctrl
, wxDatePickerCtrl
) );
527 variant
= ctrl
->GetValue();
532 void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty
* property
,
533 wxWindow
* wnd
) const
535 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
536 wxASSERT( wxDynamicCast(ctrl
, wxDatePickerCtrl
) );
538 wxDateProperty
* prop
= wxDynamicCast(property
, wxDateProperty
);
542 int datePickerStyle
= prop
->GetDatePickerStyle();
543 if ( datePickerStyle
& wxDP_ALLOWNONE
)
544 ctrl
->SetValue(wxInvalidDateTime
);
548 #endif // wxUSE_DATEPICKCTRL
551 // -----------------------------------------------------------------------
553 // -----------------------------------------------------------------------
555 #include "wx/fontdlg.h"
556 #include "wx/fontenum.h"
559 // NB: Do not use wxS here since unlike wxT it doesn't translate to wxChar*
562 static const wxChar
* const gs_fp_es_family_labels
[] = {
563 wxT("Default"), wxT("Decorative"),
564 wxT("Roman"), wxT("Script"),
565 wxT("Swiss"), wxT("Modern"),
566 wxT("Teletype"), wxT("Unknown"),
570 static const long gs_fp_es_family_values
[] = {
571 wxFONTFAMILY_DEFAULT
, wxFONTFAMILY_DECORATIVE
,
572 wxFONTFAMILY_ROMAN
, wxFONTFAMILY_SCRIPT
,
573 wxFONTFAMILY_SWISS
, wxFONTFAMILY_MODERN
,
574 wxFONTFAMILY_TELETYPE
, wxFONTFAMILY_UNKNOWN
577 static const wxChar
* const gs_fp_es_style_labels
[] = {
584 static const long gs_fp_es_style_values
[] = {
590 static const wxChar
* const gs_fp_es_weight_labels
[] = {
597 static const long gs_fp_es_weight_values
[] = {
603 // Class body is in advprops.h
606 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty
,wxPGProperty
,
607 wxFont
,const wxFont
&,TextCtrlAndButton
)
610 wxFontProperty::wxFontProperty( const wxString
& label
, const wxString
& name
,
611 const wxFont
& value
)
612 : wxPGProperty(label
,name
)
614 SetValue(WXVARIANT(value
));
616 // Initialize font family choices list
617 if ( !wxPGGlobalVars
->m_fontFamilyChoices
)
619 wxArrayString faceNames
= wxFontEnumerator::GetFacenames();
623 wxPGGlobalVars
->m_fontFamilyChoices
= new wxPGChoices(faceNames
);
626 wxString
emptyString(wxEmptyString
);
631 AddPrivateChild( new wxIntProperty( _("Point Size"),
632 wxS("Point Size"),(long)font
.GetPointSize() ) );
634 wxString faceName
= font
.GetFaceName();
635 // If font was not in there, add it now
636 if ( !faceName
.empty() &&
637 wxPGGlobalVars
->m_fontFamilyChoices
->Index(faceName
) == wxNOT_FOUND
)
638 wxPGGlobalVars
->m_fontFamilyChoices
->AddAsSorted(faceName
);
640 wxPGProperty
* p
= new wxEnumProperty(_("Face Name"), wxS("Face Name"),
641 *wxPGGlobalVars
->m_fontFamilyChoices
);
643 p
->SetValueFromString(faceName
, wxPG_FULL_VALUE
);
645 AddPrivateChild( p
);
647 AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
648 gs_fp_es_style_labels
,gs_fp_es_style_values
,
651 AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
652 gs_fp_es_weight_labels
,gs_fp_es_weight_values
,
655 AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
656 font
.GetUnderlined()) );
658 AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
659 gs_fp_es_family_labels
,gs_fp_es_family_values
,
663 wxFontProperty::~wxFontProperty() { }
665 void wxFontProperty::OnSetValue()
672 m_value
<< *wxNORMAL_FONT
;
676 wxString
wxFontProperty::ValueToString( wxVariant
& value
,
679 return wxPGProperty::ValueToString(value
, argFlags
);
682 bool wxFontProperty::OnEvent( wxPropertyGrid
* propgrid
, wxWindow
* WXUNUSED(primary
),
685 if ( propgrid
->IsMainButtonEvent(event
) )
687 // Update value from last minute changes
688 wxVariant useValue
= propgrid
->GetUncommittedPropertyValue();
693 if ( useValue
.GetType() == wxS("wxFont") )
696 data
.SetInitialFont( font
);
697 data
.SetColour(*wxBLACK
);
699 wxFontDialog
dlg(propgrid
, data
);
700 if ( dlg
.ShowModal() == wxID_OK
)
702 propgrid
->EditorsValueWasModified();
705 variant
<< dlg
.GetFontData().GetChosenFont();
706 SetValueInEvent( variant
);
713 void wxFontProperty::RefreshChildren()
715 if ( !GetChildCount() ) return;
718 Item(0)->SetValue( (long)font
.GetPointSize() );
719 Item(1)->SetValueFromString( font
.GetFaceName(), wxPG_FULL_VALUE
);
720 Item(2)->SetValue( (long)font
.GetStyle() );
721 Item(3)->SetValue( (long)font
.GetWeight() );
722 Item(4)->SetValue( font
.GetUnderlined() );
723 Item(5)->SetValue( (long)font
.GetFamily() );
726 wxVariant
wxFontProperty::ChildChanged( wxVariant
& thisValue
,
728 wxVariant
& childValue
) const
735 font
.SetPointSize( childValue
.GetLong() );
740 int faceIndex
= childValue
.GetLong();
742 if ( faceIndex
>= 0 )
743 faceName
= wxPGGlobalVars
->m_fontFamilyChoices
->GetLabel(faceIndex
);
745 font
.SetFaceName( faceName
);
749 int st
= childValue
.GetLong();
750 if ( st
!= wxFONTSTYLE_NORMAL
&&
751 st
!= wxFONTSTYLE_SLANT
&&
752 st
!= wxFONTSTYLE_ITALIC
)
753 st
= wxFONTWEIGHT_NORMAL
;
758 int wt
= childValue
.GetLong();
759 if ( wt
!= wxFONTWEIGHT_NORMAL
&&
760 wt
!= wxFONTWEIGHT_LIGHT
&&
761 wt
!= wxFONTWEIGHT_BOLD
)
762 wt
= wxFONTWEIGHT_NORMAL
;
763 font
.SetWeight( wt
);
767 font
.SetUnderlined( childValue
.GetBool() );
771 int fam
= childValue
.GetLong();
772 if ( fam
< wxDEFAULT
||
775 font
.SetFamily( fam
);
778 wxVariant newVariant
;
784 wxSize wxFontProperty::OnMeasureImage() const
786 return wxSize(-1,-1);
789 void wxFontProperty::OnCustomPaint(wxDC& dc,
791 wxPGPaintData& paintData)
794 if ( paintData.m_choiceItem >= 0 )
795 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
797 drawFace = m_value_wxFont.GetFaceName();
799 if ( !drawFace.empty() )
801 // Draw the background
802 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
803 //dc.SetBrush( *wxWHITE_BRUSH );
804 //dc.SetPen( *wxMEDIUM_GREY_PEN );
805 dc.DrawRectangle( rect );
807 wxFont oldFont = dc.GetFont();
808 wxFont drawFont(oldFont.GetPointSize(),
809 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
810 dc.SetFont(drawFont);
812 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
813 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
819 // No file - just draw a white box
820 dc.SetBrush ( *wxWHITE_BRUSH );
821 dc.DrawRectangle ( rect );
827 // -----------------------------------------------------------------------
828 // wxSystemColourProperty
829 // -----------------------------------------------------------------------
831 // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
832 #define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
834 #include "wx/colordlg.h"
836 //#define wx_cp_es_syscolours_len 25
837 static const wxChar
* const gs_cp_es_syscolour_labels
[] = {
840 wxT("ActiveCaption"),
842 wxT("ButtonHighlight"),
851 wxT("HighlightText"),
852 wxT("InactiveBorder"),
853 wxT("InactiveCaption"),
854 wxT("InactiveCaptionText"),
866 static const long gs_cp_es_syscolour_values
[] = {
867 wxSYS_COLOUR_APPWORKSPACE
,
868 wxSYS_COLOUR_ACTIVEBORDER
,
869 wxSYS_COLOUR_ACTIVECAPTION
,
870 wxSYS_COLOUR_BTNFACE
,
871 wxSYS_COLOUR_BTNHIGHLIGHT
,
872 wxSYS_COLOUR_BTNSHADOW
,
873 wxSYS_COLOUR_BTNTEXT
,
874 wxSYS_COLOUR_CAPTIONTEXT
,
875 wxSYS_COLOUR_3DDKSHADOW
,
876 wxSYS_COLOUR_3DLIGHT
,
877 wxSYS_COLOUR_BACKGROUND
,
878 wxSYS_COLOUR_GRAYTEXT
,
879 wxSYS_COLOUR_HIGHLIGHT
,
880 wxSYS_COLOUR_HIGHLIGHTTEXT
,
881 wxSYS_COLOUR_INACTIVEBORDER
,
882 wxSYS_COLOUR_INACTIVECAPTION
,
883 wxSYS_COLOUR_INACTIVECAPTIONTEXT
,
885 wxSYS_COLOUR_SCROLLBAR
,
887 wxSYS_COLOUR_INFOTEXT
,
889 wxSYS_COLOUR_WINDOWFRAME
,
890 wxSYS_COLOUR_WINDOWTEXT
,
895 IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue
, WXDLLIMPEXP_PROPGRID
)
898 // Class body is in advprops.h
900 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty
,wxEnumProperty
,
901 wxColourPropertyValue
,const wxColourPropertyValue
&,Choice
)
904 void wxSystemColourProperty::Init( int type
, const wxColour
& colour
)
906 wxColourPropertyValue cpv
;
909 cpv
.Init( type
, colour
);
911 cpv
.Init( type
, *wxWHITE
);
913 m_flags
|= wxPG_PROP_STATIC_CHOICES
; // Colour selection cannot be changed.
921 static wxPGChoices gs_wxSystemColourProperty_choicesCache
;
924 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
925 const wxColourPropertyValue
& value
)
926 : wxEnumProperty( label
,
928 gs_cp_es_syscolour_labels
,
929 gs_cp_es_syscolour_values
,
930 &gs_wxSystemColourProperty_choicesCache
)
933 Init( value
.m_type
, value
.m_colour
);
935 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
939 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
940 const wxChar
* const* labels
, const long* values
, wxPGChoices
* choicesCache
,
941 const wxColourPropertyValue
& value
)
942 : wxEnumProperty( label
, name
, labels
, values
, choicesCache
)
945 Init( value
.m_type
, value
.m_colour
);
947 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
951 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
952 const wxChar
* const* labels
, const long* values
, wxPGChoices
* choicesCache
,
953 const wxColour
& value
)
954 : wxEnumProperty( label
, name
, labels
, values
, choicesCache
)
957 Init( wxPG_COLOUR_CUSTOM
, value
);
959 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
963 wxSystemColourProperty::~wxSystemColourProperty() { }
966 wxColourPropertyValue
wxSystemColourProperty::GetVal( const wxVariant
* pVariant
) const
971 if ( pVariant
->IsNull() )
972 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED
, wxColour());
974 if ( pVariant
->GetType() == wxS("wxColourPropertyValue") )
976 wxColourPropertyValue v
;
982 bool variantProcessed
= true;
984 if ( pVariant
->GetType() == wxS("wxColour*") )
986 wxColour
* pCol
= wxStaticCast(pVariant
->GetWxObjectPtr(), wxColour
);
989 else if ( pVariant
->GetType() == wxS("wxColour") )
993 else if ( pVariant
->GetType() == wxArrayInt_VariantType
)
995 // This code is mostly needed for wxPython bindings, which
996 // may offer tuple of integers as colour value.
1000 if ( arr
.size() >= 3 )
1008 if ( arr
.size() >= 4 )
1011 col
= wxColour(r
, g
, b
, a
);
1015 variantProcessed
= false;
1020 variantProcessed
= false;
1023 if ( !variantProcessed
)
1024 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED
, wxColour());
1026 wxColourPropertyValue
v2( wxPG_COLOUR_CUSTOM
, col
);
1028 int colInd
= ColToInd(col
);
1029 if ( colInd
!= wxNOT_FOUND
)
1035 wxVariant
wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue
& v
) const
1042 int wxSystemColourProperty::ColToInd( const wxColour
& colour
) const
1045 size_t i_max
= m_choices
.GetCount();
1047 if ( !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1050 for ( i
=0; i
<i_max
; i
++ )
1052 int ind
= m_choices
[i
].GetValue();
1054 if ( colour
== GetColour(ind
) )
1056 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1057 GetClassName(),GetLabel().c_str(),
1058 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1059 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1066 void wxSystemColourProperty::OnSetValue()
1068 // Convert from generic wxobject ptr to wxPGVariantDataColour
1069 if ( m_value
.GetType() == wxS("wxColour*") )
1071 wxColour
* pCol
= wxStaticCast(m_value
.GetWxObjectPtr(), wxColour
);
1075 wxColourPropertyValue val
= GetVal(&m_value
);
1077 if ( val
.m_type
== wxPG_COLOUR_UNSPECIFIED
)
1085 if ( val
.m_type
< wxPG_COLOUR_WEB_BASE
)
1086 val
.m_colour
= GetColour( val
.m_type
);
1088 m_value
= TranslateVal(val
);
1091 int ind
= wxNOT_FOUND
;
1093 if ( m_value
.GetType() == wxS("wxColourPropertyValue") )
1095 wxColourPropertyValue cpv
;
1097 wxColour col
= cpv
.m_colour
;
1101 SetValueToUnspecified();
1102 SetIndex(wxNOT_FOUND
);
1106 if ( cpv
.m_type
< wxPG_COLOUR_WEB_BASE
||
1107 (m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1109 ind
= GetIndexForValue(cpv
.m_type
);
1113 cpv
.m_type
= wxPG_COLOUR_CUSTOM
;
1114 ind
= GetCustomColourIndex();
1124 SetValueToUnspecified();
1125 SetIndex(wxNOT_FOUND
);
1129 ind
= ColToInd(col
);
1131 if ( ind
== wxNOT_FOUND
&&
1132 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1133 ind
= GetCustomColourIndex();
1140 wxColour
wxSystemColourProperty::GetColour( int index
) const
1142 return wxSystemSettings::GetColour( (wxSystemColour
)index
);
1145 wxString
wxSystemColourProperty::ColourToString( const wxColour
& col
,
1147 int argFlags
) const
1150 if ( index
== wxNOT_FOUND
)
1153 if ( (argFlags
& wxPG_FULL_VALUE
) ||
1154 GetAttributeAsLong(wxPG_COLOUR_HAS_ALPHA
, 0) )
1156 return wxString::Format(wxS("(%i,%i,%i,%i)"),
1164 return wxString::Format(wxS("(%i,%i,%i)"),
1172 return m_choices
.GetLabel(index
);
1176 wxString
wxSystemColourProperty::ValueToString( wxVariant
& value
,
1177 int argFlags
) const
1179 wxColourPropertyValue val
= GetVal(&value
);
1183 if ( argFlags
& wxPG_VALUE_IS_CURRENT
)
1185 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1186 // but we should use it whenever possible.
1189 // If custom colour was selected, use invalid index, so that
1190 // ColourToString() will return properly formatted colour text.
1191 if ( index
== GetCustomColourIndex() &&
1192 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1193 index
= wxNOT_FOUND
;
1197 index
= m_choices
.Index(val
.m_type
);
1200 return ColourToString(val
.m_colour
, index
, argFlags
);
1204 wxSize
wxSystemColourProperty::OnMeasureImage( int ) const
1206 return wxPG_DEFAULT_IMAGE_SIZE
;
1210 int wxSystemColourProperty::GetCustomColourIndex() const
1212 return m_choices
.GetCount() - 1;
1216 bool wxSystemColourProperty::QueryColourFromUser( wxVariant
& variant
) const
1218 wxASSERT( m_value
.GetType() != wxPG_VARIANT_TYPE_STRING
);
1221 wxPropertyGrid
* propgrid
= GetGrid();
1222 wxASSERT( propgrid
);
1224 // Must only occur when user triggers event
1225 if ( !(propgrid
->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT
) )
1228 wxColourPropertyValue val
= GetVal();
1230 val
.m_type
= wxPG_COLOUR_CUSTOM
;
1233 data
.SetChooseFull(true);
1234 data
.SetColour(val
.m_colour
);
1236 for ( i
= 0; i
< 16; i
++)
1238 wxColour
colour(i
*16, i
*16, i
*16);
1239 data
.SetCustomColour(i
, colour
);
1242 wxColourDialog
dialog(propgrid
, &data
);
1243 if ( dialog
.ShowModal() == wxID_OK
)
1245 wxColourData retData
= dialog
.GetColourData();
1246 val
.m_colour
= retData
.GetColour();
1248 variant
= DoTranslateVal(val
);
1250 SetValueInEvent(variant
);
1259 bool wxSystemColourProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
1262 int type
= m_choices
.GetValue(index
);
1264 if ( type
== wxPG_COLOUR_CUSTOM
)
1266 QueryColourFromUser(variant
);
1270 variant
= TranslateVal( type
, GetColour(type
) );
1276 // Need to do some extra event handling.
1277 bool wxSystemColourProperty::OnEvent( wxPropertyGrid
* propgrid
,
1278 wxWindow
* WXUNUSED(primary
),
1281 bool askColour
= false;
1283 if ( propgrid
->IsMainButtonEvent(event
) )
1285 // We need to handle button click in case editor has been
1286 // switched to one that has wxButton as well.
1289 else if ( event
.GetEventType() == wxEVT_COMBOBOX
)
1291 // Must override index detection since at this point GetIndex()
1292 // will return old value.
1293 wxOwnerDrawnComboBox
* cb
=
1294 static_cast<wxOwnerDrawnComboBox
*>(propgrid
->GetEditorControl());
1298 int index
= cb
->GetSelection();
1300 if ( index
== GetCustomColourIndex() &&
1301 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1306 if ( askColour
&& !propgrid
->WasValueChangedInEvent() )
1309 if ( QueryColourFromUser(variant
) )
1315 /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1318 virtual void Render( wxDC& dc, const wxRect& rect,
1319 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1320 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1322 wxASSERT( wxDynamicCast(property, wxSystemColourProperty) );
1323 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1325 dc.SetPen(*wxBLACK_PEN);
1327 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1331 const wxArrayInt& values = prop->GetValues();
1332 if ( values.GetChildCount() )
1333 colInd = values[item];
1336 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1338 else if ( !prop->IsValueUnspecified() )
1339 dc.SetBrush( prop->GetVal().m_colour );
1341 dc.SetBrush( *wxWHITE );
1343 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1344 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1345 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1346 imageRect.width, imageRect.height );
1350 text = property->GetValueAsString();
1352 text = property->GetChoiceString(item);
1353 DrawText( dc, rect, imageRect.width, text );
1358 wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1360 wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1363 return &g_wxPGColourPropertyRenderer;
1364 return wxEnumProperty::GetCellRenderer(column);
1367 void wxSystemColourProperty::OnCustomPaint( wxDC
& dc
, const wxRect
& rect
,
1368 wxPGPaintData
& paintdata
)
1372 if ( paintdata
.m_choiceItem
>= 0 &&
1373 paintdata
.m_choiceItem
< (int)m_choices
.GetCount() &&
1374 (paintdata
.m_choiceItem
!= GetCustomColourIndex() ||
1375 m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1377 int colInd
= m_choices
[paintdata
.m_choiceItem
].GetValue();
1378 col
= GetColour( colInd
);
1380 else if ( !IsValueUnspecified() )
1382 col
= GetVal().m_colour
;
1388 dc
.DrawRectangle(rect
);
1393 bool wxSystemColourProperty::StringToValue( wxVariant
& value
, const wxString
& text
, int argFlags
) const
1395 wxString
custColName(m_choices
.GetLabel(GetCustomColourIndex()));
1396 wxString
colStr(text
);
1400 wxColour customColour
;
1401 bool conversionSuccess
= false;
1403 if ( colStr
!= custColName
)
1405 if ( colStr
.Find(wxS("(")) == 0 )
1407 // Eliminate whitespace
1408 colStr
.Replace(wxS(" "), wxEmptyString
);
1410 int commaCount
= colStr
.Freq(wxS(','));
1411 if ( commaCount
== 2 )
1413 // Convert (R,G,B) to rgb(R,G,B)
1414 colStr
= wxS("rgb") + colStr
;
1416 else if ( commaCount
== 3 )
1418 // We have int alpha, CSS format that wxColour takes as
1419 // input processes float alpha. So, let's parse the colour
1420 // ourselves instead of trying to convert it to a format
1421 // that wxColour::FromString() understands.
1422 int r
= -1, g
= -1, b
= -1, a
= -1;
1423 wxSscanf(colStr
, wxS("(%i,%i,%i,%i)"), &r
, &g
, &b
, &a
);
1424 customColour
.Set(r
, g
, b
, a
);
1425 conversionSuccess
= customColour
.IsOk();
1429 if ( !conversionSuccess
)
1430 conversionSuccess
= customColour
.Set(colStr
);
1433 if ( !conversionSuccess
&& m_choices
.GetCount() &&
1434 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) &&
1435 colStr
== custColName
)
1437 if ( !(argFlags
& wxPG_EDITABLE_VALUE
))
1439 // This really should not occur...
1445 QueryColourFromUser(value
);
1449 wxColourPropertyValue val
;
1453 if ( !conversionSuccess
)
1455 // Try predefined colour first
1456 bool res
= wxEnumProperty::StringToValue(value
,
1459 if ( res
&& GetIndex() >= 0 )
1461 val
.m_type
= GetIndex();
1462 if ( val
.m_type
< m_choices
.GetCount() )
1463 val
.m_type
= m_choices
[val
.m_type
].GetValue();
1465 // Get proper colour for type.
1466 val
.m_colour
= GetColour(val
.m_type
);
1473 val
.m_type
= wxPG_COLOUR_CUSTOM
;
1474 val
.m_colour
= customColour
;
1484 value
= DoTranslateVal(val
);
1491 bool wxSystemColourProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1493 if ( name
== wxPG_COLOUR_ALLOW_CUSTOM
)
1495 int ival
= value
.GetLong();
1497 if ( ival
&& (m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1499 // Show custom choice
1500 m_choices
.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM
);
1501 m_flags
&= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR
);
1503 else if ( !ival
&& !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1505 // Hide custom choice
1506 m_choices
.RemoveAt(GetCustomColourIndex());
1507 m_flags
|= wxPG_PROP_HIDE_CUSTOM_COLOUR
;
1515 // -----------------------------------------------------------------------
1517 // -----------------------------------------------------------------------
1519 static const wxChar
* const gs_cp_es_normcolour_labels
[] = {
1539 (const wxChar
*) NULL
1542 static const unsigned long gs_cp_es_normcolour_colours
[] = {
1544 wxPG_COLOUR(128,0,0),
1545 wxPG_COLOUR(0,0,128),
1546 wxPG_COLOUR(128,0,128),
1547 wxPG_COLOUR(0,128,128),
1548 wxPG_COLOUR(128,128,128),
1549 wxPG_COLOUR(0,128,0),
1550 wxPG_COLOUR(128,128,0),
1551 wxPG_COLOUR(166,124,81),
1552 wxPG_COLOUR(0,0,255),
1553 wxPG_COLOUR(255,0,255),
1554 wxPG_COLOUR(255,0,0),
1555 wxPG_COLOUR(247,148,28),
1556 wxPG_COLOUR(192,192,192),
1557 wxPG_COLOUR(0,255,0),
1558 wxPG_COLOUR(0,255,255),
1559 wxPG_COLOUR(255,255,0),
1560 wxPG_COLOUR(255,255,255),
1564 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty
, wxSystemColourProperty
,
1565 wxColour
, const wxColour
&, TextCtrlAndButton
)
1567 static wxPGChoices gs_wxColourProperty_choicesCache
;
1569 wxColourProperty::wxColourProperty( const wxString
& label
,
1570 const wxString
& name
,
1571 const wxColour
& value
)
1572 : wxSystemColourProperty(label
, name
, gs_cp_es_normcolour_labels
,
1574 &gs_wxColourProperty_choicesCache
, value
)
1578 m_flags
|= wxPG_PROP_TRANSLATE_CUSTOM
;
1581 wxColourProperty::~wxColourProperty()
1585 void wxColourProperty::Init( wxColour colour
)
1587 if ( !colour
.IsOk() )
1592 int ind
= ColToInd(colour
);
1594 ind
= m_choices
.GetCount() - 1;
1598 wxString
wxColourProperty::ValueToString( wxVariant
& value
,
1599 int argFlags
) const
1601 const wxPGEditor
* editor
= GetEditorClass();
1602 if ( editor
!= wxPGEditor_Choice
&&
1603 editor
!= wxPGEditor_ChoiceAndButton
&&
1604 editor
!= wxPGEditor_ComboBox
)
1605 argFlags
|= wxPG_PROPERTY_SPECIFIC
;
1607 return wxSystemColourProperty::ValueToString(value
, argFlags
);
1610 wxColour
wxColourProperty::GetColour( int index
) const
1612 return gs_cp_es_normcolour_colours
[m_choices
.GetValue(index
)];
1615 wxVariant
wxColourProperty::DoTranslateVal( wxColourPropertyValue
& v
) const
1618 variant
<< v
.m_colour
;
1622 // -----------------------------------------------------------------------
1624 // -----------------------------------------------------------------------
1626 #define wxPG_CURSOR_IMAGE_WIDTH 32
1628 #define NUM_CURSORS 28
1630 //#define wx_cp_es_syscursors_len 28
1631 static const wxChar
* const gs_cp_es_syscursors_labels
[NUM_CURSORS
+1] = {
1643 wxT("Middle Button"),
1649 wxT("Question Arrow"),
1650 wxT("Right Button"),
1651 wxT("Sizing NE-SW"),
1653 wxT("Sizing NW-SE"),
1660 (const wxChar
*) NULL
1663 static const long gs_cp_es_syscursors_values
[NUM_CURSORS
] = {
1666 wxCURSOR_RIGHT_ARROW
,
1673 wxCURSOR_LEFT_BUTTON
,
1675 wxCURSOR_MIDDLE_BUTTON
,
1677 wxCURSOR_PAINT_BRUSH
,
1679 wxCURSOR_POINT_LEFT
,
1680 wxCURSOR_POINT_RIGHT
,
1681 wxCURSOR_QUESTION_ARROW
,
1682 wxCURSOR_RIGHT_BUTTON
,
1694 IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty
, wxEnumProperty
)
1696 wxCursorProperty::wxCursorProperty( const wxString
& label
, const wxString
& name
,
1698 : wxEnumProperty( label
,
1700 gs_cp_es_syscursors_labels
,
1701 gs_cp_es_syscursors_values
,
1704 m_flags
|= wxPG_PROP_STATIC_CHOICES
; // Cursor selection cannot be changed.
1707 wxCursorProperty::~wxCursorProperty()
1711 wxSize
wxCursorProperty::OnMeasureImage( int item
) const
1713 #if wxPG_CAN_DRAW_CURSOR
1714 if ( item
!= -1 && item
< NUM_CURSORS
)
1715 return wxSize(wxPG_CURSOR_IMAGE_WIDTH
,wxPG_CURSOR_IMAGE_WIDTH
);
1722 #if wxPG_CAN_DRAW_CURSOR
1724 void wxCursorProperty::OnCustomPaint( wxDC
& dc
,
1726 wxPGPaintData
& paintdata
)
1729 dc
.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
) );
1731 if ( paintdata
.m_choiceItem
>= 0 )
1733 dc
.DrawRectangle( rect
);
1735 if ( paintdata
.m_choiceItem
< NUM_CURSORS
)
1737 wxStockCursor cursorIndex
=
1738 (wxStockCursor
) gs_cp_es_syscursors_values
[paintdata
.m_choiceItem
];
1741 if ( cursorIndex
== wxCURSOR_NONE
)
1742 cursorIndex
= wxCURSOR_ARROW
;
1744 wxCursor
cursor( cursorIndex
);
1747 HDC hDc
= (HDC
)((const wxMSWDCImpl
*)dc
.GetImpl())->GetHDC();
1751 (HICON
)cursor
.GetHandle(),
1756 #if !defined(__WXWINCE__)
1757 DI_COMPAT
| DI_DEFAULTSIZE
|
1768 void wxCursorProperty::OnCustomPaint( wxDC
&, const wxRect
&, wxPGPaintData
& ) { }
1769 /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1771 return wxEnumProperty::GetCellRenderer(column);
1775 // -----------------------------------------------------------------------
1776 // wxImageFileProperty
1777 // -----------------------------------------------------------------------
1781 const wxString
& wxPGGetDefaultImageWildcard()
1783 // Form the wildcard, if not done yet
1784 if ( wxPGGlobalVars
->m_pDefaultImageWildcard
.empty() )
1789 // TODO: This section may require locking (using global).
1791 wxList
& handlers
= wxImage::GetHandlers();
1793 wxList::iterator node
;
1795 // Let's iterate over the image handler list.
1796 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1797 for ( node
= handlers
.begin(); node
!= handlers
.end(); ++node
)
1799 wxImageHandler
*handler
= (wxImageHandler
*)*node
;
1801 wxString ext_lo
= handler
->GetExtension();
1802 wxString ext_up
= ext_lo
.Upper();
1804 str
.append( ext_up
);
1805 str
.append( wxT(" files (*.") );
1806 str
.append( ext_up
);
1807 str
.append( wxT(")|*.") );
1808 str
.append( ext_lo
);
1809 str
.append( wxT("|") );
1812 str
.append ( wxT("All files (*.*)|*.*") );
1814 wxPGGlobalVars
->m_pDefaultImageWildcard
= str
;
1817 return wxPGGlobalVars
->m_pDefaultImageWildcard
;
1820 IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty
, wxFileProperty
)
1822 wxImageFileProperty::wxImageFileProperty( const wxString
& label
, const wxString
& name
,
1823 const wxString
& value
)
1824 : wxFileProperty(label
,name
,value
)
1826 SetAttribute( wxPG_FILE_WILDCARD
, wxPGGetDefaultImageWildcard() );
1832 wxImageFileProperty::~wxImageFileProperty()
1840 void wxImageFileProperty::OnSetValue()
1842 wxFileProperty::OnSetValue();
1846 wxDELETE(m_pBitmap
);
1848 wxFileName filename
= GetFileName();
1850 // Create the image thumbnail
1851 if ( filename
.FileExists() )
1853 m_pImage
= new wxImage( filename
.GetFullPath() );
1857 wxSize
wxImageFileProperty::OnMeasureImage( int ) const
1859 return wxPG_DEFAULT_IMAGE_SIZE
;
1862 void wxImageFileProperty::OnCustomPaint( wxDC
& dc
,
1866 if ( m_pBitmap
|| (m_pImage
&& m_pImage
->IsOk() ) )
1868 // Draw the thumbnail
1870 // Create the bitmap here because required size is not known in OnSetValue().
1873 m_pImage
->Rescale( rect
.width
, rect
.height
);
1874 m_pBitmap
= new wxBitmap( *m_pImage
);
1878 dc
.DrawBitmap( *m_pBitmap
, rect
.x
, rect
.y
, false );
1882 // No file - just draw a white box
1883 dc
.SetBrush( *wxWHITE_BRUSH
);
1884 dc
.DrawRectangle ( rect
);
1888 #endif // wxUSE_IMAGE
1890 // -----------------------------------------------------------------------
1891 // wxMultiChoiceProperty
1892 // -----------------------------------------------------------------------
1896 #include "wx/choicdlg.h"
1898 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty
,wxPGProperty
,
1899 wxArrayInt
,const wxArrayInt
&,TextCtrlAndButton
)
1901 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1902 const wxString
& name
,
1903 const wxPGChoices
& choices
,
1904 const wxArrayString
& value
)
1905 : wxPGProperty(label
,name
)
1907 m_choices
.Assign(choices
);
1911 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1912 const wxString
& name
,
1913 const wxArrayString
& strings
,
1914 const wxArrayString
& value
)
1915 : wxPGProperty(label
,name
)
1917 m_choices
.Set(strings
);
1921 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1922 const wxString
& name
,
1923 const wxArrayString
& value
)
1924 : wxPGProperty(label
,name
)
1926 wxArrayString strings
;
1927 m_choices
.Set(strings
);
1931 wxMultiChoiceProperty::~wxMultiChoiceProperty()
1935 void wxMultiChoiceProperty::OnSetValue()
1937 GenerateValueAsString(m_value
, &m_display
);
1940 wxString
wxMultiChoiceProperty::ValueToString( wxVariant
& value
,
1941 int argFlags
) const
1943 // If possible, use cached string
1944 if ( argFlags
& wxPG_VALUE_IS_CURRENT
)
1948 GenerateValueAsString(value
, &s
);
1952 void wxMultiChoiceProperty::GenerateValueAsString( wxVariant
& value
,
1953 wxString
* target
) const
1955 wxArrayString strings
;
1957 if ( value
.GetType() == wxPG_VARIANT_TYPE_ARRSTRING
)
1958 strings
= value
.GetArrayString();
1960 wxString
& tempStr
= *target
;
1962 unsigned int itemCount
= strings
.size();
1967 tempStr
.append( wxT("\"") );
1969 for ( i
= 0; i
< itemCount
; i
++ )
1971 tempStr
.append( strings
[i
] );
1972 tempStr
.append( wxT("\"") );
1973 if ( i
< (itemCount
-1) )
1974 tempStr
.append ( wxT(" \"") );
1978 wxArrayInt
wxMultiChoiceProperty::GetValueAsIndices() const
1980 wxVariant variant
= GetValue();
1981 const wxArrayInt
& valueArr
= wxArrayIntRefFromVariant(variant
);
1984 // Translate values to string indices.
1985 wxArrayInt selections
;
1987 if ( !m_choices
.IsOk() || !m_choices
.GetCount() || !(&valueArr
) )
1989 for ( i
=0; i
<valueArr
.size(); i
++ )
1994 for ( i
=0; i
<valueArr
.size(); i
++ )
1996 int sIndex
= m_choices
.Index(valueArr
[i
]);
1998 selections
.Add(sIndex
);
2005 bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid
* propgrid
,
2006 wxWindow
* WXUNUSED(primary
),
2009 if ( propgrid
->IsMainButtonEvent(event
) )
2012 wxVariant useValue
= propgrid
->GetUncommittedPropertyValue();
2014 wxArrayString labels
= m_choices
.GetLabels();
2015 unsigned int choiceCount
;
2017 if ( m_choices
.IsOk() )
2018 choiceCount
= m_choices
.GetCount();
2022 // launch editor dialog
2023 wxMultiChoiceDialog
dlg( propgrid
,
2024 _("Make a selection:"),
2027 choiceCount
?&labels
[0]:NULL
,
2028 wxCHOICEDLG_STYLE
);
2030 dlg
.Move( propgrid
->GetGoodEditorDialogPosition(this,dlg
.GetSize()) );
2032 wxArrayString strings
= useValue
.GetArrayString();
2033 wxArrayString extraStrings
;
2035 dlg
.SetSelections(m_choices
.GetIndicesForStrings(strings
, &extraStrings
));
2037 if ( dlg
.ShowModal() == wxID_OK
&& choiceCount
)
2039 int userStringMode
= GetAttributeAsLong(wxT("UserStringMode"), 0);
2041 wxArrayInt arrInt
= dlg
.GetSelections();
2045 // Strings that were not in list of choices
2046 wxArrayString value
;
2048 // Translate string indices to strings
2051 if ( userStringMode
== 1 )
2053 for (n
=0;n
<extraStrings
.size();n
++)
2054 value
.push_back(extraStrings
[n
]);
2058 for ( i
=0; i
<arrInt
.size(); i
++ )
2059 value
.Add(m_choices
.GetLabel(arrInt
.Item(i
)));
2061 if ( userStringMode
== 2 )
2063 for (n
=0;n
<extraStrings
.size();n
++)
2064 value
.push_back(extraStrings
[n
]);
2067 variant
= WXVARIANT(value
);
2069 SetValueInEvent(variant
);
2077 bool wxMultiChoiceProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
2081 int userStringMode
= GetAttributeAsLong(wxT("UserStringMode"), 0);
2083 WX_PG_TOKENIZER2_BEGIN(text
,wxT('"'))
2084 if ( userStringMode
> 0 || (m_choices
.IsOk() && m_choices
.Index( token
) != wxNOT_FOUND
) )
2086 WX_PG_TOKENIZER2_END()
2088 wxVariant
v( WXVARIANT(arr
) );
2094 #endif // wxUSE_CHOICEDLG
2097 // -----------------------------------------------------------------------
2099 // -----------------------------------------------------------------------
2104 #if wxUSE_DATEPICKCTRL
2105 #define dtCtrl DatePickerCtrl
2107 #define dtCtrl TextCtrl
2110 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty
,
2117 wxString
wxDateProperty::ms_defaultDateFormat
;
2120 wxDateProperty::wxDateProperty( const wxString
& label
,
2121 const wxString
& name
,
2122 const wxDateTime
& value
)
2123 : wxPGProperty(label
,name
)
2125 //wxPGRegisterDefaultValueType(wxDateTime)
2127 #if wxUSE_DATEPICKCTRL
2128 wxPGRegisterEditorClass(DatePickerCtrl
);
2130 m_dpStyle
= wxDP_DEFAULT
| wxDP_SHOWCENTURY
;
2138 wxDateProperty::~wxDateProperty()
2142 void wxDateProperty::OnSetValue()
2145 // Convert invalid dates to unspecified value
2146 if ( m_value
.GetType() == wxT("datetime") )
2148 if ( !m_value
.GetDateTime().IsValid() )
2153 bool wxDateProperty::StringToValue( wxVariant
& variant
, const wxString
& text
,
2154 int WXUNUSED(argFlags
) ) const
2158 // FIXME: do we really want to return true from here if only part of the
2159 // string was parsed?
2160 const char* c
= dt
.ParseFormat(text
);
2171 wxString
wxDateProperty::ValueToString( wxVariant
& value
,
2172 int argFlags
) const
2174 const wxChar
* format
= (const wxChar
*) NULL
;
2176 wxDateTime dateTime
= value
.GetDateTime();
2178 if ( !dateTime
.IsValid() )
2179 return wxT("Invalid");
2181 if ( ms_defaultDateFormat
.empty() )
2183 #if wxUSE_DATEPICKCTRL
2184 bool showCentury
= m_dpStyle
& wxDP_SHOWCENTURY
? true : false;
2186 bool showCentury
= true;
2188 ms_defaultDateFormat
= DetermineDefaultDateFormat( showCentury
);
2191 if ( !m_format
.empty() &&
2192 !(argFlags
& wxPG_FULL_VALUE
) )
2193 format
= m_format
.c_str();
2195 // Determine default from locale
2196 // NB: This is really simple stuff, but can't figure anything
2197 // better without proper support in wxLocale
2199 format
= ms_defaultDateFormat
.c_str();
2201 return dateTime
.Format(format
);
2204 wxString
wxDateProperty::DetermineDefaultDateFormat( bool showCentury
)
2206 // This code is basically copied from datectlg.cpp's SetFormat
2211 dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2212 wxString
str(dt
.Format(wxT("%x")));
2214 const wxChar
*p
= str
.c_str();
2218 if (n
== dt
.GetDay())
2220 format
.Append(wxT("%d"));
2223 else if (n
== (int)dt
.GetMonth()+1)
2225 format
.Append(wxT("%m"));
2228 else if (n
== dt
.GetYear())
2230 format
.Append(wxT("%Y"));
2233 else if (n
== (dt
.GetYear() % 100))
2236 format
.Append(wxT("%Y"));
2238 format
.Append(wxT("%y"));
2242 format
.Append(*p
++);
2248 bool wxDateProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
2250 if ( name
== wxPG_DATE_FORMAT
)
2252 m_format
= value
.GetString();
2255 else if ( name
== wxPG_DATE_PICKER_STYLE
)
2257 m_dpStyle
= value
.GetLong();
2258 ms_defaultDateFormat
.clear(); // This may need recalculation
2264 #endif // wxUSE_DATETIME
2267 // -----------------------------------------------------------------------
2268 // wxPropertyGridInterface
2269 // -----------------------------------------------------------------------
2271 void wxPropertyGridInterface::InitAllTypeHandlers()
2275 // -----------------------------------------------------------------------
2277 void wxPropertyGridInterface::RegisterAdditionalEditors()
2279 // Register editor classes, if necessary.
2280 if ( wxPGGlobalVars
->m_mapEditorClasses
.empty() )
2281 wxPropertyGrid::RegisterDefaultEditors();
2284 wxPGRegisterEditorClass(SpinCtrl
);
2286 #if wxUSE_DATEPICKCTRL
2287 wxPGRegisterEditorClass(DatePickerCtrl
);
2291 // -----------------------------------------------------------------------
2293 #endif // wxPG_INCLUDE_ADVPROPS
2295 #endif // wxUSE_PROPGRID