1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/advprops.cpp
3 // Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.)
4 // Author: Jaakko Salli
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/object.h"
25 #include "wx/string.h"
28 #include "wx/window.h"
31 #include "wx/dcclient.h"
32 #include "wx/button.h"
35 #include "wx/cursor.h"
36 #include "wx/dialog.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/choice.h"
40 #include "wx/stattext.h"
41 #include "wx/textctrl.h"
42 #include "wx/scrolwin.h"
43 #include "wx/dirdlg.h"
44 #include "wx/combobox.h"
46 #include "wx/textdlg.h"
47 #include "wx/filedlg.h"
49 #include "wx/wxcrtvararg.h"
52 #define __wxPG_SOURCE_FILE__
54 #include "wx/propgrid/propgrid.h"
56 #if wxPG_INCLUDE_ADVPROPS
58 #include "wx/propgrid/advprops.h"
61 #include "wx/msw/private.h"
62 #include "wx/msw/dc.h"
65 // -----------------------------------------------------------------------
67 #if defined(__WXMSW__)
68 #define wxPG_CAN_DRAW_CURSOR 1
69 #elif defined(__WXGTK__)
70 #define wxPG_CAN_DRAW_CURSOR 0
71 #elif defined(__WXMAC__)
72 #define wxPG_CAN_DRAW_CURSOR 0
74 #define wxPG_CAN_DRAW_CURSOR 0
78 // -----------------------------------------------------------------------
80 // -----------------------------------------------------------------------
83 // Implement dynamic class for type value.
84 IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue
, wxObject
)
86 bool operator == (const wxColourPropertyValue
& a
, const wxColourPropertyValue
& b
)
88 return ( ( a
.m_colour
== b
.m_colour
) && (a
.m_type
== b
.m_type
) );
91 bool operator == (const wxArrayInt
& array1
, const wxArrayInt
& array2
)
93 if ( array1
.size() != array2
.size() )
96 for ( i
=0; i
<array1
.size(); i
++ )
98 if ( array1
[i
] != array2
[i
] )
104 // -----------------------------------------------------------------------
105 // wxSpinCtrl-based property editor
106 // -----------------------------------------------------------------------
112 #define IS_MOTION_SPIN_SUPPORTED 1
114 #define IS_MOTION_SPIN_SUPPORTED 0
117 #if IS_MOTION_SPIN_SUPPORTED
120 // This class implements ability to rapidly change "spin" value
121 // by moving mouse when one of the spin buttons is depressed.
122 class wxPGSpinButton
: public wxSpinButton
125 wxPGSpinButton() : wxSpinButton()
128 m_hasCapture
= false;
131 Connect( wxEVT_LEFT_DOWN
,
132 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
133 Connect( wxEVT_LEFT_UP
,
134 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
135 Connect( wxEVT_MOTION
,
136 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
137 Connect( wxEVT_MOUSE_CAPTURE_LOST
,
138 wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost
) );
147 wxPoint m_ptPosition
;
149 // Having a separate spins variable allows us to handle validation etc. for
150 // multiple spin events at once (with quick mouse movements there could be
151 // hundreds of 'spins' being done at once). Technically things like this
152 // should be stored in event (wxSpinEvent in this case), but there probably
153 // isn't anything there that can be reliably reused.
158 // SpinButton seems to be a special for mouse capture, so we may need track
159 // privately whether mouse is actually captured.
170 SetCursor(wxCURSOR_SIZENS
);
179 m_hasCapture
= false;
182 wxWindow
*parent
= GetParent();
184 SetCursor(parent
->GetCursor());
186 SetCursor(wxNullCursor
);
189 void OnMouseEvent(wxMouseEvent
& event
)
191 if ( event
.GetEventType() == wxEVT_LEFT_DOWN
)
194 m_ptPosition
= event
.GetPosition();
196 else if ( event
.GetEventType() == wxEVT_LEFT_UP
)
201 else if ( event
.GetEventType() == wxEVT_MOTION
)
205 int dy
= m_ptPosition
.y
- event
.GetPosition().y
;
209 m_ptPosition
= event
.GetPosition();
211 wxSpinEvent
evtscroll( (dy
>= 0) ? wxEVT_SCROLL_LINEUP
:
212 wxEVT_SCROLL_LINEDOWN
,
214 evtscroll
.SetEventObject(this);
216 wxASSERT( m_spins
== 1 );
219 GetEventHandler()->ProcessEvent(evtscroll
);
227 void OnMouseCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
))
233 #endif // IS_MOTION_SPIN_SUPPORTED
236 WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl
,
241 // Trivial destructor.
242 wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
247 // Create controls and initialize event handling.
248 wxPGWindowList
wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
249 const wxPoint
& pos
, const wxSize
& sz
) const
251 const int margin
= 1;
252 wxSize
butSz(18, sz
.y
);
253 wxSize
tcSz(sz
.x
- butSz
.x
- margin
, sz
.y
);
254 wxPoint
butPos(pos
.x
+ tcSz
.x
+ margin
, pos
.y
);
258 #if IS_MOTION_SPIN_SUPPORTED
259 if ( property
->GetAttributeAsLong(wxT("MotionSpin"), 0) )
261 wnd2
= new wxPGSpinButton();
266 wnd2
= new wxSpinButton();
272 wnd2
->Create( propgrid
->GetPanel(), wxPG_SUBID2
, butPos
, butSz
, wxSP_VERTICAL
);
274 wnd2
->SetRange( INT_MIN
, INT_MAX
);
277 // Let's add validator to make sure only numbers can be entered
278 wxTextValidator
validator(wxFILTER_NUMERIC
, &m_tempString
);
280 wxTextCtrl
* wnd1
= (wxTextCtrl
*) wxPGTextCtrlEditor::CreateControls( propgrid
, property
, pos
, tcSz
).m_primary
;
281 wnd1
->SetValidator(validator
);
283 return wxPGWindowList(wnd1
, wnd2
);
286 // Control's events are redirected here
287 bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
288 wxWindow
* wnd
, wxEvent
& event
) const
290 int evtType
= event
.GetEventType();
293 bool bigStep
= false;
295 if ( evtType
== wxEVT_KEY_DOWN
)
297 wxKeyEvent
& keyEvent
= (wxKeyEvent
&)event
;
298 keycode
= keyEvent
.GetKeyCode();
300 if ( keycode
== WXK_UP
)
301 evtType
= wxEVT_SCROLL_LINEUP
;
302 else if ( keycode
== WXK_DOWN
)
303 evtType
= wxEVT_SCROLL_LINEDOWN
;
304 else if ( keycode
== WXK_PAGEUP
)
306 evtType
= wxEVT_SCROLL_LINEUP
;
309 else if ( keycode
== WXK_PAGEDOWN
)
311 evtType
= wxEVT_SCROLL_LINEDOWN
;
316 if ( evtType
== wxEVT_SCROLL_LINEUP
|| evtType
== wxEVT_SCROLL_LINEDOWN
)
318 #if IS_MOTION_SPIN_SUPPORTED
319 if ( property
->GetAttributeAsLong(wxT("MotionSpin"), 0) )
321 wxPGSpinButton
* spinButton
=
322 (wxPGSpinButton
*) propgrid
->GetEditorControlSecondary();
325 spins
= spinButton
->GetSpins();
330 // Can't use wnd since it might be clipper window
331 wxTextCtrl
* tc
= wxDynamicCast(propgrid
->GetEditorControl(), wxTextCtrl
);
336 s
= property
->GetValueAsString(wxPG_FULL_VALUE
);
338 int mode
= wxPG_PROPERTY_VALIDATION_SATURATE
;
340 if ( property
->GetAttributeAsLong(wxT("Wrap"), 0) )
341 mode
= wxPG_PROPERTY_VALIDATION_WRAP
;
343 if ( property
->GetValueType() == wxT("double") )
346 double step
= property
->GetAttributeAsDouble(wxT("Step"), 1.0);
349 if ( s
.ToDouble(&v_d
) )
354 step
*= (double) spins
;
356 if ( evtType
== wxEVT_SCROLL_LINEUP
) v_d
+= step
;
360 wxFloatProperty::DoValidation(property
, v_d
, NULL
, mode
);
362 wxPropertyGrid::DoubleToString(s
, v_d
, 6, true, NULL
);
372 wxLongLong_t step
= property
->GetAttributeAsLong(wxT("Step"), 1);
375 if ( s
.ToLongLong(&v_ll
, 10) )
382 if ( evtType
== wxEVT_SCROLL_LINEUP
) v_ll
+= step
;
386 wxIntProperty::DoValidation(property
, v_ll
, NULL
, mode
);
388 s
= wxLongLong(v_ll
).ToString();
398 int ip
= tc
->GetInsertionPoint();
399 int lp
= tc
->GetLastPosition();
401 tc
->SetInsertionPoint(ip
+(tc
->GetLastPosition()-lp
));
407 return wxPGTextCtrlEditor::OnEvent(propgrid
,property
,wnd
,event
);
410 #endif // wxUSE_SPINBTN
413 // -----------------------------------------------------------------------
414 // wxDatePickerCtrl-based property editor
415 // -----------------------------------------------------------------------
417 #if wxUSE_DATEPICKCTRL
420 #include "wx/datectrl.h"
421 #include "wx/dateevt.h"
423 class wxPGDatePickerCtrlEditor
: public wxPGEditor
425 DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor
)
427 virtual ~wxPGDatePickerCtrlEditor();
429 wxString
GetName() const;
430 virtual wxPGWindowList
CreateControls(wxPropertyGrid
* propgrid
,
431 wxPGProperty
* property
,
433 const wxSize
& size
) const;
434 virtual void UpdateControl( wxPGProperty
* property
, wxWindow
* wnd
) const;
435 virtual bool OnEvent( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
436 wxWindow
* wnd
, wxEvent
& event
) const;
437 virtual bool GetValueFromControl( wxVariant
& variant
, wxPGProperty
* property
, wxWindow
* wnd
) const;
438 virtual void SetValueToUnspecified( wxPGProperty
* WXUNUSED(property
), wxWindow
* wnd
) const;
442 WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl
,
443 wxPGDatePickerCtrlEditor
,
447 wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
451 wxPGWindowList
wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid
* propgrid
,
452 wxPGProperty
* property
,
454 const wxSize
& sz
) const
456 wxCHECK_MSG( property
->IsKindOf(CLASSINFO(wxDateProperty
)),
458 wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
460 wxDateProperty
* prop
= wxDynamicCast(property
, wxDateProperty
);
462 // Use two stage creation to allow cleaner display on wxMSW
463 wxDatePickerCtrl
* ctrl
= new wxDatePickerCtrl();
466 wxSize useSz
= wxDefaultSize
;
472 wxDateTime
dateValue(wxInvalidDateTime
);
474 wxVariant value
= prop
->GetValue();
475 if ( value
.GetType() == wxT("datetime") )
476 dateValue
= value
.GetDateTime();
478 ctrl
->Create(propgrid
->GetPanel(),
483 prop
->GetDatePickerStyle() | wxNO_BORDER
);
492 // Copies value from property to control
493 void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty
* property
,
494 wxWindow
* wnd
) const
496 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
497 wxASSERT( ctrl
&& ctrl
->IsKindOf(CLASSINFO(wxDatePickerCtrl
)) );
499 wxDateTime
dateValue(wxInvalidDateTime
);
500 wxVariant
v(property
->GetValue());
501 if ( v
.GetType() == wxT("datetime") )
502 dateValue
= v
.GetDateTime();
504 ctrl
->SetValue( dateValue
);
507 // Control's events are redirected here
508 bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid
* WXUNUSED(propgrid
),
509 wxPGProperty
* WXUNUSED(property
),
510 wxWindow
* WXUNUSED(wnd
),
511 wxEvent
& event
) const
513 if ( event
.GetEventType() == wxEVT_DATE_CHANGED
)
519 bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant
& variant
, wxPGProperty
* WXUNUSED(property
), wxWindow
* wnd
) const
521 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
522 wxASSERT( ctrl
&& ctrl
->IsKindOf(CLASSINFO(wxDatePickerCtrl
)) );
524 variant
= ctrl
->GetValue();
529 void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty
* property
,
530 wxWindow
* wnd
) const
532 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
533 wxASSERT( ctrl
&& ctrl
->IsKindOf(CLASSINFO(wxDatePickerCtrl
)) );
535 wxDateProperty
* prop
= wxDynamicCast(property
, wxDateProperty
);
539 int datePickerStyle
= prop
->GetDatePickerStyle();
540 if ( datePickerStyle
& wxDP_ALLOWNONE
)
541 ctrl
->SetValue(wxInvalidDateTime
);
545 #endif // wxUSE_DATEPICKCTRL
548 // -----------------------------------------------------------------------
550 // -----------------------------------------------------------------------
552 #include "wx/fontdlg.h"
553 #include "wx/fontenum.h"
555 static const wxChar
* gs_fp_es_family_labels
[] = {
556 wxT("Default"), wxT("Decorative"),
557 wxT("Roman"), wxT("Script"),
558 wxT("Swiss"), wxT("Modern"),
562 static long gs_fp_es_family_values
[] = {
563 wxDEFAULT
, wxDECORATIVE
,
568 static const wxChar
* gs_fp_es_style_labels
[] = {
575 static long gs_fp_es_style_values
[] = {
581 static const wxChar
* gs_fp_es_weight_labels
[] = {
588 static long gs_fp_es_weight_values
[] = {
594 // Class body is in advprops.h
597 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty
,wxPGProperty
,
598 wxFont
,const wxFont
&,TextCtrlAndButton
)
601 wxFontProperty::wxFontProperty( const wxString
& label
, const wxString
& name
,
602 const wxFont
& value
)
603 : wxPGProperty(label
,name
)
605 SetValue(WXVARIANT(value
));
607 // Initialize font family choices list
608 if ( !wxPGGlobalVars
->m_fontFamilyChoices
)
610 wxArrayString faceNames
= wxFontEnumerator::GetFacenames();
614 wxPGGlobalVars
->m_fontFamilyChoices
= new wxPGChoices(faceNames
);
617 wxString
emptyString(wxEmptyString
);
622 SetParentalType(wxPG_PROP_AGGREGATE
);
624 AddChild( new wxIntProperty( _("Point Size"), wxS("Point Size"),(long)font
.GetPointSize() ) );
626 AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
627 gs_fp_es_family_labels
,gs_fp_es_family_values
,
630 wxString faceName
= font
.GetFaceName();
631 // If font was not in there, add it now
632 if ( faceName
.length() &&
633 wxPGGlobalVars
->m_fontFamilyChoices
->Index(faceName
) == wxNOT_FOUND
)
634 wxPGGlobalVars
->m_fontFamilyChoices
->AddAsSorted(faceName
);
636 wxPGProperty
* p
= new wxEnumProperty(_("Face Name"), wxS("Face Name"),
637 *wxPGGlobalVars
->m_fontFamilyChoices
);
639 p
->SetValueFromString(faceName
, wxPG_FULL_VALUE
);
643 AddChild( new wxEnumProperty(_("Style"), wxS("Style"),
644 gs_fp_es_style_labels
,gs_fp_es_style_values
,font
.GetStyle()) );
646 AddChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
647 gs_fp_es_weight_labels
,gs_fp_es_weight_values
,font
.GetWeight()) );
649 AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
650 font
.GetUnderlined()) );
653 wxFontProperty::~wxFontProperty() { }
655 void wxFontProperty::OnSetValue()
662 font
= wxFont(10,wxSWISS
,wxNORMAL
,wxNORMAL
);
667 wxString
wxFontProperty::ValueToString( wxVariant
& value
,
670 return wxPGProperty::ValueToString(value
, argFlags
);
673 bool wxFontProperty::OnEvent( wxPropertyGrid
* propgrid
, wxWindow
* WXUNUSED(primary
),
676 if ( propgrid
->IsMainButtonEvent(event
) )
678 // Update value from last minute changes
679 wxVariant useValue
= propgrid
->GetUncommittedPropertyValue();
684 data
.SetInitialFont( font
);
685 data
.SetColour(*wxBLACK
);
687 wxFontDialog
dlg(propgrid
, data
);
688 if ( dlg
.ShowModal() == wxID_OK
)
690 propgrid
->EditorsValueWasModified();
693 variant
<< dlg
.GetFontData().GetChosenFont();
694 SetValueInEvent( variant
);
701 void wxFontProperty::RefreshChildren()
703 if ( !GetChildCount() ) return;
706 Item(0)->SetValue( (long)font
.GetPointSize() );
707 Item(1)->SetValue( (long)font
.GetFamily() );
708 Item(2)->SetValueFromString( font
.GetFaceName(), wxPG_FULL_VALUE
);
709 Item(3)->SetValue( (long)font
.GetStyle() );
710 Item(4)->SetValue( (long)font
.GetWeight() );
711 Item(5)->SetValue( font
.GetUnderlined() );
714 void wxFontProperty::ChildChanged( wxVariant
& thisValue
, int ind
, wxVariant
& childValue
) const
721 font
.SetPointSize( wxPGVariantToInt(childValue
) );
725 int fam
= childValue
.GetLong();
726 if ( fam
< wxDEFAULT
||
729 font
.SetFamily( fam
);
734 int faceIndex
= childValue
.GetLong();
736 if ( faceIndex
>= 0 )
737 faceName
= wxPGGlobalVars
->m_fontFamilyChoices
->GetLabel(faceIndex
);
739 font
.SetFaceName( faceName
);
743 int st
= childValue
.GetLong();
744 if ( st
!= wxFONTSTYLE_NORMAL
&&
745 st
!= wxFONTSTYLE_SLANT
&&
746 st
!= wxFONTSTYLE_ITALIC
)
747 st
= wxFONTWEIGHT_NORMAL
;
752 int wt
= childValue
.GetLong();
753 if ( wt
!= wxFONTWEIGHT_NORMAL
&&
754 wt
!= wxFONTWEIGHT_LIGHT
&&
755 wt
!= wxFONTWEIGHT_BOLD
)
756 wt
= wxFONTWEIGHT_NORMAL
;
757 font
.SetWeight( wt
);
761 font
.SetUnderlined( childValue
.GetBool() );
768 wxSize wxFontProperty::OnMeasureImage() const
770 return wxSize(-1,-1);
773 void wxFontProperty::OnCustomPaint(wxDC& dc,
775 wxPGPaintData& paintData)
778 if ( paintData.m_choiceItem >= 0 )
779 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
781 drawFace = m_value_wxFont.GetFaceName();
783 if ( drawFace.length() )
785 // Draw the background
786 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
787 //dc.SetBrush( *wxWHITE_BRUSH );
788 //dc.SetPen( *wxMEDIUM_GREY_PEN );
789 dc.DrawRectangle( rect );
791 wxFont oldFont = dc.GetFont();
792 wxFont drawFont(oldFont.GetPointSize(),
793 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
794 dc.SetFont(drawFont);
796 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
797 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
803 // No file - just draw a white box
804 dc.SetBrush ( *wxWHITE_BRUSH );
805 dc.DrawRectangle ( rect );
811 // -----------------------------------------------------------------------
812 // wxSystemColourProperty
813 // -----------------------------------------------------------------------
815 // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
816 #define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
818 #include "wx/colordlg.h"
820 //#define wx_cp_es_syscolours_len 25
821 static const wxChar
* gs_cp_es_syscolour_labels
[] = {
824 wxT("ActiveCaption"),
826 wxT("ButtonHighlight"),
835 wxT("HighlightText"),
836 wxT("InactiveBorder"),
837 wxT("InactiveCaption"),
838 wxT("InactiveCaptionText"),
850 static long gs_cp_es_syscolour_values
[] = {
851 wxSYS_COLOUR_APPWORKSPACE
,
852 wxSYS_COLOUR_ACTIVEBORDER
,
853 wxSYS_COLOUR_ACTIVECAPTION
,
854 wxSYS_COLOUR_BTNFACE
,
855 wxSYS_COLOUR_BTNHIGHLIGHT
,
856 wxSYS_COLOUR_BTNSHADOW
,
857 wxSYS_COLOUR_BTNTEXT
,
858 wxSYS_COLOUR_CAPTIONTEXT
,
859 wxSYS_COLOUR_3DDKSHADOW
,
860 wxSYS_COLOUR_3DLIGHT
,
861 wxSYS_COLOUR_BACKGROUND
,
862 wxSYS_COLOUR_GRAYTEXT
,
863 wxSYS_COLOUR_HIGHLIGHT
,
864 wxSYS_COLOUR_HIGHLIGHTTEXT
,
865 wxSYS_COLOUR_INACTIVEBORDER
,
866 wxSYS_COLOUR_INACTIVECAPTION
,
867 wxSYS_COLOUR_INACTIVECAPTIONTEXT
,
869 wxSYS_COLOUR_SCROLLBAR
,
871 wxSYS_COLOUR_INFOTEXT
,
873 wxSYS_COLOUR_WINDOWFRAME
,
874 wxSYS_COLOUR_WINDOWTEXT
,
879 IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue
, WXDLLIMPEXP_PROPGRID
)
882 // Class body is in advprops.h
884 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty
,wxEnumProperty
,
885 wxColourPropertyValue
,const wxColourPropertyValue
&,Choice
)
888 void wxSystemColourProperty::Init( int type
, const wxColour
& colour
)
890 wxColourPropertyValue cpv
;
893 cpv
.Init( type
, colour
);
895 cpv
.Init( type
, *wxWHITE
);
897 m_flags
|= wxPG_PROP_STATIC_CHOICES
; // Colour selection cannot be changed.
905 static wxPGChoices gs_wxSystemColourProperty_choicesCache
;
908 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
909 const wxColourPropertyValue
& value
)
910 : wxEnumProperty( label
,
912 gs_cp_es_syscolour_labels
,
913 gs_cp_es_syscolour_values
,
914 &gs_wxSystemColourProperty_choicesCache
)
917 Init( value
.m_type
, value
.m_colour
);
919 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
923 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
924 const wxChar
** labels
, const long* values
, wxPGChoices
* choicesCache
,
925 const wxColourPropertyValue
& value
)
926 : wxEnumProperty( label
, name
, labels
, values
, choicesCache
)
929 Init( value
.m_type
, value
.m_colour
);
931 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
935 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
936 const wxChar
** labels
, const long* values
, wxPGChoices
* choicesCache
,
937 const wxColour
& value
)
938 : wxEnumProperty( label
, name
, labels
, values
, choicesCache
)
941 Init( wxPG_COLOUR_CUSTOM
, value
);
943 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
947 wxSystemColourProperty::~wxSystemColourProperty() { }
950 wxColourPropertyValue
wxSystemColourProperty::GetVal( const wxVariant
* pVariant
) const
955 if ( pVariant
->IsNull() )
956 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED
, wxColour());
958 if ( pVariant
->GetType() == wxS("wxColourPropertyValue") )
960 wxColourPropertyValue v
;
966 bool variantProcessed
= true;
968 if ( pVariant
->GetType() == wxS("wxColour*") )
970 wxColour
* pCol
= wxStaticCast(pVariant
->GetWxObjectPtr(), wxColour
);
973 else if ( pVariant
->GetType() == wxS("wxColour") )
977 else if ( pVariant
->GetType() == wxArrayInt_VariantType
)
979 // This code is mostly needed for wxPython bindings, which
980 // may offer tuple of integers as colour value.
984 if ( arr
.size() >= 3 )
992 if ( arr
.size() >= 4 )
995 col
= wxColour(r
, g
, b
, a
);
999 variantProcessed
= false;
1004 variantProcessed
= false;
1007 if ( !variantProcessed
)
1008 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED
, wxColour());
1010 wxColourPropertyValue
v2( wxPG_COLOUR_CUSTOM
, col
);
1012 int colInd
= ColToInd(col
);
1013 if ( colInd
!= wxNOT_FOUND
)
1019 wxVariant
wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue
& v
) const
1026 int wxSystemColourProperty::ColToInd( const wxColour
& colour
) const
1029 size_t i_max
= m_choices
.GetCount() - 1;
1031 for ( i
=0; i
<i_max
; i
++ )
1033 int ind
= m_choices
[i
].GetValue();
1035 if ( colour
== GetColour(ind
) )
1037 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1038 GetClassName(),GetLabel().c_str(),
1039 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1040 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1047 void wxSystemColourProperty::OnSetValue()
1049 // Convert from generic wxobject ptr to wxPGVariantDataColour
1050 if ( m_value
.GetType() == wxS("wxColour*") )
1052 wxColour
* pCol
= wxStaticCast(m_value
.GetWxObjectPtr(), wxColour
);
1056 wxColourPropertyValue val
= GetVal(&m_value
);
1058 if ( val
.m_type
== wxPG_COLOUR_UNSPECIFIED
)
1066 if ( val
.m_type
< wxPG_COLOUR_WEB_BASE
)
1067 val
.m_colour
= GetColour( val
.m_type
);
1069 m_value
= TranslateVal(val
);
1072 int ind
= wxNOT_FOUND
;
1074 if ( m_value
.GetType() == wxS("wxColourPropertyValue") )
1076 wxColourPropertyValue cpv
;
1078 wxColour col
= cpv
.m_colour
;
1082 SetValueToUnspecified();
1083 SetIndex(wxNOT_FOUND
);
1087 if ( cpv
.m_type
< wxPG_COLOUR_WEB_BASE
)
1089 ind
= GetIndexForValue(cpv
.m_type
);
1093 cpv
.m_type
= wxPG_COLOUR_CUSTOM
;
1094 ind
= GetCustomColourIndex();
1104 SetValueToUnspecified();
1105 SetIndex(wxNOT_FOUND
);
1109 ind
= ColToInd(col
);
1111 if ( ind
== wxNOT_FOUND
)
1112 ind
= GetCustomColourIndex();
1119 wxColour
wxSystemColourProperty::GetColour( int index
) const
1121 return wxSystemSettings::GetColour( (wxSystemColour
)index
);
1124 wxString
wxSystemColourProperty::ColourToString( const wxColour
& col
, int index
) const
1126 if ( index
== wxNOT_FOUND
)
1127 return wxString::Format(wxT("(%i,%i,%i)"),
1132 return m_choices
.GetLabel(index
);
1135 wxString
wxSystemColourProperty::ValueToString( wxVariant
& value
,
1136 int argFlags
) const
1138 wxColourPropertyValue val
= GetVal(&value
);
1142 if ( argFlags
& wxPG_VALUE_IS_CURRENT
)
1144 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1145 // but we should use it whenever possible.
1148 // If custom colour was selected, use invalid index, so that
1149 // ColourToString() will return properly formatted colour text.
1150 if ( index
== GetCustomColourIndex() )
1151 index
= wxNOT_FOUND
;
1155 index
= m_choices
.Index(val
.m_type
);
1158 return ColourToString(val
.m_colour
, index
);
1162 wxSize
wxSystemColourProperty::OnMeasureImage( int ) const
1164 return wxPG_DEFAULT_IMAGE_SIZE
;
1168 int wxSystemColourProperty::GetCustomColourIndex() const
1170 return m_choices
.GetCount() - 1;
1174 bool wxSystemColourProperty::QueryColourFromUser( wxVariant
& variant
) const
1176 wxASSERT( m_value
.GetType() != wxPG_VARIANT_TYPE_STRING
);
1179 wxPropertyGrid
* propgrid
= GetGrid();
1180 wxASSERT( propgrid
);
1182 // Must only occur when user triggers event
1183 if ( !(propgrid
->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT
) )
1186 wxColourPropertyValue val
= GetVal();
1188 val
.m_type
= wxPG_COLOUR_CUSTOM
;
1191 data
.SetChooseFull(true);
1192 data
.SetColour(val
.m_colour
);
1194 for ( i
= 0; i
< 16; i
++)
1196 wxColour
colour(i
*16, i
*16, i
*16);
1197 data
.SetCustomColour(i
, colour
);
1200 wxColourDialog
dialog(propgrid
, &data
);
1201 if ( dialog
.ShowModal() == wxID_OK
)
1203 wxColourData retData
= dialog
.GetColourData();
1204 val
.m_colour
= retData
.GetColour();
1206 variant
= DoTranslateVal(val
);
1208 SetValueInEvent(variant
);
1217 bool wxSystemColourProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
1220 int type
= m_choices
.GetValue(index
);
1222 if ( type
== wxPG_COLOUR_CUSTOM
)
1224 QueryColourFromUser(variant
);
1228 variant
= TranslateVal( type
, GetColour(type
) );
1234 // Need to do some extra event handling.
1235 bool wxSystemColourProperty::OnEvent( wxPropertyGrid
* propgrid
, wxWindow
* WXUNUSED(primary
), wxEvent
& event
)
1237 if ( propgrid
->IsMainButtonEvent(event
) )
1239 // We need to handle button click in case editor has been
1240 // switched to one that has wxButton as well.
1242 if ( QueryColourFromUser(variant
) )
1248 /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1251 virtual void Render( wxDC& dc, const wxRect& rect,
1252 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1253 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1255 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1256 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1258 dc.SetPen(*wxBLACK_PEN);
1260 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1264 const wxArrayInt& values = prop->GetValues();
1265 if ( values.GetChildCount() )
1266 colInd = values[item];
1269 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1271 else if ( !prop->IsValueUnspecified() )
1272 dc.SetBrush( prop->GetVal().m_colour );
1274 dc.SetBrush( *wxWHITE );
1276 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1277 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1278 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1279 imageRect.width, imageRect.height );
1283 text = property->GetValueAsString();
1285 text = property->GetChoiceString(item);
1286 DrawText( dc, rect, imageRect.width, text );
1291 wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1293 wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1296 return &g_wxPGColourPropertyRenderer;
1297 return wxEnumProperty::GetCellRenderer(column);
1300 void wxSystemColourProperty::OnCustomPaint( wxDC
& dc
, const wxRect
& rect
,
1301 wxPGPaintData
& paintdata
)
1305 if ( paintdata
.m_choiceItem
>= 0 && paintdata
.m_choiceItem
< (int)m_choices
.GetCount() &&
1306 paintdata
.m_choiceItem
!= GetCustomColourIndex() )
1308 int colInd
= m_choices
[paintdata
.m_choiceItem
].GetValue();
1309 col
= GetColour( colInd
);
1311 else if ( !IsValueUnspecified() )
1313 col
= GetVal().m_colour
;
1319 dc
.DrawRectangle(rect
);
1324 bool wxSystemColourProperty::StringToValue( wxVariant
& value
, const wxString
& text
, int argFlags
) const
1327 // Accept colour format "[Name] [(R,G,B)]"
1328 // Name takes precedence.
1330 wxString colourName
;
1333 int ppos
= text
.Find(wxT("("));
1335 if ( ppos
== wxNOT_FOUND
)
1341 colourName
= text
.substr(0, ppos
);
1342 colourRGB
= text
.substr(ppos
, text
.length()-ppos
);
1345 // Strip spaces from extremities
1346 colourName
.Trim(true);
1347 colourName
.Trim(false);
1348 colourRGB
.Trim(true);
1350 // Validate colourRGB string - (1,1,1) is shortest allowed
1351 if ( colourRGB
.length() < 7 )
1354 if ( colourRGB
.length() == 0 && m_choices
.GetCount() &&
1355 colourName
== m_choices
.GetLabel(GetCustomColourIndex()) )
1357 if ( !(argFlags
& wxPG_EDITABLE_VALUE
))
1359 // This really should not occurr...
1365 QueryColourFromUser(value
);
1369 wxColourPropertyValue val
;
1373 if ( colourName
.length() )
1375 // Try predefined colour first
1376 bool res
= wxEnumProperty::StringToValue(value
, colourName
, argFlags
);
1377 if ( res
&& GetIndex() >= 0 )
1379 val
.m_type
= GetIndex();
1380 if ( val
.m_type
< m_choices
.GetCount() )
1381 val
.m_type
= m_choices
[val
.m_type
].GetValue();
1383 // Get proper colour for type.
1384 val
.m_colour
= GetColour(val
.m_type
);
1389 if ( colourRGB
.length() && !done
)
1391 // Then check custom colour.
1392 val
.m_type
= wxPG_COLOUR_CUSTOM
;
1394 int r
= -1, g
= -1, b
= -1;
1395 wxSscanf(colourRGB
.c_str(),wxT("(%i,%i,%i)"),&r
,&g
,&b
);
1397 if ( r
>= 0 && r
<= 255 &&
1398 g
>= 0 && g
<= 255 &&
1399 b
>= 0 && b
<= 255 )
1401 val
.m_colour
.Set(r
,g
,b
);
1413 value
= DoTranslateVal(val
);
1420 bool wxSystemColourProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1422 if ( name
== wxPG_COLOUR_ALLOW_CUSTOM
)
1424 int ival
= wxPGVariantToInt(value
);
1426 if ( ival
&& (m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1428 // Show custom choice
1429 m_choices
.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM
);
1430 m_flags
&= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR
);
1432 else if ( !ival
&& !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1434 // Hide custom choice
1435 m_choices
.RemoveAt(GetCustomColourIndex());
1436 m_flags
|= wxPG_PROP_HIDE_CUSTOM_COLOUR
;
1444 // -----------------------------------------------------------------------
1446 // -----------------------------------------------------------------------
1448 static const wxChar
* gs_cp_es_normcolour_labels
[] = {
1468 (const wxChar
*) NULL
1471 static unsigned long gs_cp_es_normcolour_colours
[] = {
1473 wxPG_COLOUR(128,0,0),
1474 wxPG_COLOUR(0,0,128),
1475 wxPG_COLOUR(128,0,128),
1476 wxPG_COLOUR(0,128,128),
1477 wxPG_COLOUR(128,128,128),
1478 wxPG_COLOUR(0,128,0),
1479 wxPG_COLOUR(128,128,0),
1480 wxPG_COLOUR(166,124,81),
1481 wxPG_COLOUR(0,0,255),
1482 wxPG_COLOUR(255,0,255),
1483 wxPG_COLOUR(255,0,0),
1484 wxPG_COLOUR(247,148,28),
1485 wxPG_COLOUR(192,192,192),
1486 wxPG_COLOUR(0,255,0),
1487 wxPG_COLOUR(0,255,255),
1488 wxPG_COLOUR(255,255,0),
1489 wxPG_COLOUR(255,255,255),
1493 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty
, wxSystemColourProperty
,
1494 wxColour
, const wxColour
&, TextCtrlAndButton
)
1496 static wxPGChoices gs_wxColourProperty_choicesCache
;
1498 wxColourProperty::wxColourProperty( const wxString
& label
,
1499 const wxString
& name
,
1500 const wxColour
& value
)
1501 : wxSystemColourProperty(label
, name
, gs_cp_es_normcolour_labels
,
1503 &gs_wxColourProperty_choicesCache
, value
)
1507 m_flags
|= wxPG_PROP_TRANSLATE_CUSTOM
;
1510 wxColourProperty::~wxColourProperty()
1514 void wxColourProperty::Init( wxColour colour
)
1521 int ind
= ColToInd(colour
);
1523 ind
= m_choices
.GetCount() - 1;
1527 wxString
wxColourProperty::ValueToString( wxVariant
& value
,
1528 int argFlags
) const
1530 const wxPGEditor
* editor
= GetEditorClass();
1531 if ( editor
!= wxPGEditor_Choice
&&
1532 editor
!= wxPGEditor_ChoiceAndButton
&&
1533 editor
!= wxPGEditor_ComboBox
)
1534 argFlags
|= wxPG_PROPERTY_SPECIFIC
;
1536 return wxSystemColourProperty::ValueToString(value
, argFlags
);
1539 wxColour
wxColourProperty::GetColour( int index
) const
1541 return gs_cp_es_normcolour_colours
[m_choices
.GetValue(index
)];
1544 wxVariant
wxColourProperty::DoTranslateVal( wxColourPropertyValue
& v
) const
1547 variant
<< v
.m_colour
;
1551 // -----------------------------------------------------------------------
1553 // -----------------------------------------------------------------------
1555 #define wxPG_CURSOR_IMAGE_WIDTH 32
1557 #define NUM_CURSORS 28
1559 //#define wx_cp_es_syscursors_len 28
1560 static const wxChar
* gs_cp_es_syscursors_labels
[NUM_CURSORS
+1] = {
1572 wxT("Middle Button"),
1578 wxT("Question Arrow"),
1579 wxT("Right Button"),
1580 wxT("Sizing NE-SW"),
1582 wxT("Sizing NW-SE"),
1589 (const wxChar
*) NULL
1592 static long gs_cp_es_syscursors_values
[NUM_CURSORS
] = {
1595 wxCURSOR_RIGHT_ARROW
,
1602 wxCURSOR_LEFT_BUTTON
,
1604 wxCURSOR_MIDDLE_BUTTON
,
1606 wxCURSOR_PAINT_BRUSH
,
1608 wxCURSOR_POINT_LEFT
,
1609 wxCURSOR_POINT_RIGHT
,
1610 wxCURSOR_QUESTION_ARROW
,
1611 wxCURSOR_RIGHT_BUTTON
,
1623 IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty
, wxEnumProperty
)
1625 wxCursorProperty::wxCursorProperty( const wxString
& label
, const wxString
& name
,
1627 : wxEnumProperty( label
,
1629 gs_cp_es_syscursors_labels
,
1630 gs_cp_es_syscursors_values
,
1633 m_flags
|= wxPG_PROP_STATIC_CHOICES
; // Cursor selection cannot be changed.
1636 wxCursorProperty::~wxCursorProperty()
1640 wxSize
wxCursorProperty::OnMeasureImage( int item
) const
1642 #if wxPG_CAN_DRAW_CURSOR
1643 if ( item
!= -1 && item
< NUM_CURSORS
)
1644 return wxSize(wxPG_CURSOR_IMAGE_WIDTH
,wxPG_CURSOR_IMAGE_WIDTH
);
1651 #if wxPG_CAN_DRAW_CURSOR
1653 void wxCursorProperty::OnCustomPaint( wxDC
& dc
,
1655 wxPGPaintData
& paintdata
)
1658 dc
.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
) );
1660 if ( paintdata
.m_choiceItem
>= 0 )
1662 dc
.DrawRectangle( rect
);
1664 if ( paintdata
.m_choiceItem
< NUM_CURSORS
)
1666 wxStockCursor cursorIndex
=
1667 (wxStockCursor
) gs_cp_es_syscursors_values
[paintdata
.m_choiceItem
];
1670 if ( cursorIndex
== wxCURSOR_NONE
)
1671 cursorIndex
= wxCURSOR_ARROW
;
1673 wxCursor
cursor( cursorIndex
);
1676 HDC hDc
= (HDC
)((const wxMSWDCImpl
*)dc
.GetImpl())->GetHDC();
1680 (HICON
)cursor
.GetHandle(),
1685 #if !defined(__WXWINCE__)
1686 DI_COMPAT
| DI_DEFAULTSIZE
|
1697 void wxCursorProperty::OnCustomPaint( wxDC
&, const wxRect
&, wxPGPaintData
& ) { }
1698 /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1700 return wxEnumProperty::GetCellRenderer(column);
1704 // -----------------------------------------------------------------------
1705 // wxImageFileProperty
1706 // -----------------------------------------------------------------------
1710 const wxString
& wxPGGetDefaultImageWildcard()
1712 // Form the wildcard, if not done yet
1713 if ( !wxPGGlobalVars
->m_pDefaultImageWildcard
.length() )
1718 // TODO: This section may require locking (using global).
1720 wxList
& handlers
= wxImage::GetHandlers();
1722 wxList::iterator node
;
1724 // Let's iterate over the image handler list.
1725 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1726 for ( node
= handlers
.begin(); node
!= handlers
.end(); ++node
)
1728 wxImageHandler
*handler
= (wxImageHandler
*)*node
;
1730 wxString ext_lo
= handler
->GetExtension();
1731 wxString ext_up
= ext_lo
.Upper();
1733 str
.append( ext_up
);
1734 str
.append( wxT(" files (*.") );
1735 str
.append( ext_up
);
1736 str
.append( wxT(")|*.") );
1737 str
.append( ext_lo
);
1738 str
.append( wxT("|") );
1741 str
.append ( wxT("All files (*.*)|*.*") );
1743 wxPGGlobalVars
->m_pDefaultImageWildcard
= str
;
1746 return wxPGGlobalVars
->m_pDefaultImageWildcard
;
1749 IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty
, wxFileProperty
)
1751 wxImageFileProperty::wxImageFileProperty( const wxString
& label
, const wxString
& name
,
1752 const wxString
& value
)
1753 : wxFileProperty(label
,name
,value
)
1755 SetAttribute( wxPG_FILE_WILDCARD
, wxPGGetDefaultImageWildcard() );
1761 wxImageFileProperty::~wxImageFileProperty()
1769 void wxImageFileProperty::OnSetValue()
1771 wxFileProperty::OnSetValue();
1785 wxFileName filename
= GetFileName();
1787 // Create the image thumbnail
1788 if ( filename
.FileExists() )
1790 m_pImage
= new wxImage( filename
.GetFullPath() );
1794 wxSize
wxImageFileProperty::OnMeasureImage( int ) const
1796 return wxPG_DEFAULT_IMAGE_SIZE
;
1799 void wxImageFileProperty::OnCustomPaint( wxDC
& dc
,
1803 if ( m_pBitmap
|| (m_pImage
&& m_pImage
->Ok() ) )
1805 // Draw the thumbnail
1807 // Create the bitmap here because required size is not known in OnSetValue().
1810 m_pImage
->Rescale( rect
.width
, rect
.height
);
1811 m_pBitmap
= new wxBitmap( *m_pImage
);
1816 dc
.DrawBitmap( *m_pBitmap
, rect
.x
, rect
.y
, false );
1820 // No file - just draw a white box
1821 dc
.SetBrush( *wxWHITE_BRUSH
);
1822 dc
.DrawRectangle ( rect
);
1826 #endif // wxUSE_IMAGE
1828 // -----------------------------------------------------------------------
1829 // wxMultiChoiceProperty
1830 // -----------------------------------------------------------------------
1834 #include "wx/choicdlg.h"
1836 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty
,wxPGProperty
,
1837 wxArrayInt
,const wxArrayInt
&,TextCtrlAndButton
)
1839 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1840 const wxString
& name
,
1841 const wxPGChoices
& choices
,
1842 const wxArrayString
& value
)
1843 : wxPGProperty(label
,name
)
1845 m_choices
.Assign(choices
);
1849 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1850 const wxString
& name
,
1851 const wxArrayString
& strings
,
1852 const wxArrayString
& value
)
1853 : wxPGProperty(label
,name
)
1855 m_choices
.Set(strings
);
1859 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1860 const wxString
& name
,
1861 const wxArrayString
& value
)
1862 : wxPGProperty(label
,name
)
1864 wxArrayString strings
;
1865 m_choices
.Set(strings
);
1869 wxMultiChoiceProperty::~wxMultiChoiceProperty()
1873 void wxMultiChoiceProperty::OnSetValue()
1875 GenerateValueAsString(m_value
, &m_display
);
1878 wxString
wxMultiChoiceProperty::ValueToString( wxVariant
& value
,
1879 int argFlags
) const
1881 // If possible, use cached string
1882 if ( argFlags
& wxPG_VALUE_IS_CURRENT
)
1886 GenerateValueAsString(value
, &s
);
1890 void wxMultiChoiceProperty::GenerateValueAsString( wxVariant
& value
,
1891 wxString
* target
) const
1893 wxArrayString strings
;
1895 if ( value
.GetType() == wxPG_VARIANT_TYPE_ARRSTRING
)
1896 strings
= value
.GetArrayString();
1898 wxString
& tempStr
= *target
;
1900 unsigned int itemCount
= strings
.size();
1905 tempStr
.append( wxT("\"") );
1907 for ( i
= 0; i
< itemCount
; i
++ )
1909 tempStr
.append( strings
[i
] );
1910 tempStr
.append( wxT("\"") );
1911 if ( i
< (itemCount
-1) )
1912 tempStr
.append ( wxT(" \"") );
1916 wxArrayInt
wxMultiChoiceProperty::GetValueAsIndices() const
1918 wxVariant variant
= GetValue();
1919 const wxArrayInt
& valueArr
= wxArrayIntRefFromVariant(variant
);
1922 // Translate values to string indices.
1923 wxArrayInt selections
;
1925 if ( !m_choices
.IsOk() || !m_choices
.GetCount() || !(&valueArr
) )
1927 for ( i
=0; i
<valueArr
.size(); i
++ )
1932 for ( i
=0; i
<valueArr
.size(); i
++ )
1934 int sIndex
= m_choices
.Index(valueArr
[i
]);
1936 selections
.Add(sIndex
);
1943 bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid
* propgrid
,
1944 wxWindow
* WXUNUSED(primary
),
1947 if ( propgrid
->IsMainButtonEvent(event
) )
1950 wxVariant useValue
= propgrid
->GetUncommittedPropertyValue();
1952 wxArrayString labels
= m_choices
.GetLabels();
1953 unsigned int choiceCount
;
1955 if ( m_choices
.IsOk() )
1956 choiceCount
= m_choices
.GetCount();
1960 // launch editor dialog
1961 wxMultiChoiceDialog
dlg( propgrid
,
1962 _("Make a selection:"),
1965 choiceCount
?&labels
[0]:NULL
,
1966 wxCHOICEDLG_STYLE
);
1968 dlg
.Move( propgrid
->GetGoodEditorDialogPosition(this,dlg
.GetSize()) );
1970 wxArrayString strings
= useValue
.GetArrayString();
1971 wxArrayString extraStrings
;
1973 dlg
.SetSelections(m_choices
.GetIndicesForStrings(strings
, &extraStrings
));
1975 if ( dlg
.ShowModal() == wxID_OK
&& choiceCount
)
1977 int userStringMode
= GetAttributeAsLong(wxT("UserStringMode"), 0);
1979 wxArrayInt arrInt
= dlg
.GetSelections();
1983 // Strings that were not in list of choices
1984 wxArrayString value
;
1986 // Translate string indices to strings
1989 if ( userStringMode
== 1 )
1991 for (n
=0;n
<extraStrings
.size();n
++)
1992 value
.push_back(extraStrings
[n
]);
1996 for ( i
=0; i
<arrInt
.size(); i
++ )
1997 value
.Add(m_choices
.GetLabel(arrInt
.Item(i
)));
1999 if ( userStringMode
== 2 )
2001 for (n
=0;n
<extraStrings
.size();n
++)
2002 value
.push_back(extraStrings
[n
]);
2005 variant
= WXVARIANT(value
);
2007 SetValueInEvent(variant
);
2015 bool wxMultiChoiceProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
2019 int userStringMode
= GetAttributeAsLong(wxT("UserStringMode"), 0);
2021 WX_PG_TOKENIZER2_BEGIN(text
,wxT('"'))
2022 if ( userStringMode
> 0 || (m_choices
.IsOk() && m_choices
.Index( token
) != wxNOT_FOUND
) )
2024 WX_PG_TOKENIZER2_END()
2026 wxVariant
v( WXVARIANT(arr
) );
2032 #endif // wxUSE_CHOICEDLG
2035 // -----------------------------------------------------------------------
2037 // -----------------------------------------------------------------------
2042 #if wxUSE_DATEPICKCTRL
2043 #define dtCtrl DatePickerCtrl
2045 #define dtCtrl TextCtrl
2048 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty
,
2055 wxString
wxDateProperty::ms_defaultDateFormat
;
2058 wxDateProperty::wxDateProperty( const wxString
& label
,
2059 const wxString
& name
,
2060 const wxDateTime
& value
)
2061 : wxPGProperty(label
,name
)
2063 //wxPGRegisterDefaultValueType(wxDateTime)
2065 #if wxUSE_DATEPICKCTRL
2066 wxPGRegisterEditorClass(DatePickerCtrl
);
2068 m_dpStyle
= wxDP_DEFAULT
| wxDP_SHOWCENTURY
;
2076 wxDateProperty::~wxDateProperty()
2080 void wxDateProperty::OnSetValue()
2083 // Convert invalid dates to unspecified value
2084 if ( m_value
.GetType() == wxT("datetime") )
2086 if ( !m_value
.GetDateTime().IsValid() )
2091 bool wxDateProperty::StringToValue( wxVariant
& variant
, const wxString
& text
,
2092 int WXUNUSED(argFlags
) ) const
2096 const char* c
= dt
.ParseFormat(text
, wxString(wxDefaultDateTimeFormat
), wxDefaultDateTime
, NULL
);
2107 wxString
wxDateProperty::ValueToString( wxVariant
& value
,
2108 int argFlags
) const
2110 const wxChar
* format
= (const wxChar
*) NULL
;
2112 wxDateTime dateTime
= value
.GetDateTime();
2114 if ( !dateTime
.IsValid() )
2115 return wxT("Invalid");
2117 if ( !ms_defaultDateFormat
.length() )
2119 #if wxUSE_DATEPICKCTRL
2120 bool showCentury
= m_dpStyle
& wxDP_SHOWCENTURY
? true : false;
2122 bool showCentury
= true;
2124 ms_defaultDateFormat
= DetermineDefaultDateFormat( showCentury
);
2127 if ( m_format
.length() &&
2128 !(argFlags
& wxPG_FULL_VALUE
) )
2129 format
= m_format
.c_str();
2131 // Determine default from locale
2132 // NB: This is really simple stuff, but can't figure anything
2133 // better without proper support in wxLocale
2135 format
= ms_defaultDateFormat
.c_str();
2137 return dateTime
.Format(format
);
2140 wxString
wxDateProperty::DetermineDefaultDateFormat( bool showCentury
)
2142 // This code is basicly copied from datectlg.cpp's SetFormat
2147 dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2148 wxString
str(dt
.Format(wxT("%x")));
2150 const wxChar
*p
= str
.c_str();
2154 if (n
== dt
.GetDay())
2156 format
.Append(wxT("%d"));
2159 else if (n
== (int)dt
.GetMonth()+1)
2161 format
.Append(wxT("%m"));
2164 else if (n
== dt
.GetYear())
2166 format
.Append(wxT("%Y"));
2169 else if (n
== (dt
.GetYear() % 100))
2172 format
.Append(wxT("%Y"));
2174 format
.Append(wxT("%y"));
2178 format
.Append(*p
++);
2184 bool wxDateProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
2186 if ( name
== wxPG_DATE_FORMAT
)
2188 m_format
= value
.GetString();
2191 else if ( name
== wxPG_DATE_PICKER_STYLE
)
2193 m_dpStyle
= value
.GetLong();
2194 ms_defaultDateFormat
.clear(); // This may need recalculation
2200 #endif // wxUSE_DATETIME
2203 // -----------------------------------------------------------------------
2204 // wxPropertyGridInterface
2205 // -----------------------------------------------------------------------
2207 void wxPropertyGridInterface::InitAllTypeHandlers()
2211 // -----------------------------------------------------------------------
2213 void wxPropertyGridInterface::RegisterAdditionalEditors()
2215 // Register editor classes, if necessary.
2216 if ( wxPGGlobalVars
->m_mapEditorClasses
.empty() )
2217 wxPropertyGrid::RegisterDefaultEditors();
2220 wxPGRegisterEditorClass(SpinCtrl
);
2222 #if wxUSE_DATEPICKCTRL
2223 wxPGRegisterEditorClass(DatePickerCtrl
);
2227 // -----------------------------------------------------------------------
2229 #endif // wxPG_INCLUDE_ADVPROPS
2231 #endif // wxUSE_PROPGRID