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 licence
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 #include "wx/odcombo.h"
67 // -----------------------------------------------------------------------
69 #if defined(__WXMSW__)
70 #define wxPG_CAN_DRAW_CURSOR 1
71 #elif defined(__WXGTK__)
72 #define wxPG_CAN_DRAW_CURSOR 0
73 #elif defined(__WXMAC__)
74 #define wxPG_CAN_DRAW_CURSOR 0
76 #define wxPG_CAN_DRAW_CURSOR 0
80 // -----------------------------------------------------------------------
82 // -----------------------------------------------------------------------
85 // Implement dynamic class for type value.
86 IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue
, wxObject
)
88 bool operator == (const wxColourPropertyValue
& a
, const wxColourPropertyValue
& b
)
90 return ( ( a
.m_colour
== b
.m_colour
) && (a
.m_type
== b
.m_type
) );
93 bool operator == (const wxArrayInt
& array1
, const wxArrayInt
& array2
)
95 if ( array1
.size() != array2
.size() )
98 for ( i
=0; i
<array1
.size(); i
++ )
100 if ( array1
[i
] != array2
[i
] )
106 // -----------------------------------------------------------------------
107 // wxSpinCtrl-based property editor
108 // -----------------------------------------------------------------------
114 #define IS_MOTION_SPIN_SUPPORTED 1
116 #define IS_MOTION_SPIN_SUPPORTED 0
119 #if IS_MOTION_SPIN_SUPPORTED
122 // This class implements ability to rapidly change "spin" value
123 // by moving mouse when one of the spin buttons is depressed.
124 class wxPGSpinButton
: public wxSpinButton
127 wxPGSpinButton() : wxSpinButton()
130 m_hasCapture
= false;
133 Connect( wxEVT_LEFT_DOWN
,
134 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
135 Connect( wxEVT_LEFT_UP
,
136 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
137 Connect( wxEVT_MOTION
,
138 wxMouseEventHandler(wxPGSpinButton::OnMouseEvent
) );
139 Connect( wxEVT_MOUSE_CAPTURE_LOST
,
140 wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost
) );
149 wxPoint m_ptPosition
;
151 // Having a separate spins variable allows us to handle validation etc. for
152 // multiple spin events at once (with quick mouse movements there could be
153 // hundreds of 'spins' being done at once). Technically things like this
154 // should be stored in event (wxSpinEvent in this case), but there probably
155 // isn't anything there that can be reliably reused.
160 // SpinButton seems to be a special for mouse capture, so we may need track
161 // privately whether mouse is actually captured.
172 SetCursor(wxCURSOR_SIZENS
);
181 m_hasCapture
= false;
184 wxWindow
*parent
= GetParent();
186 SetCursor(parent
->GetCursor());
188 SetCursor(wxNullCursor
);
191 void OnMouseEvent(wxMouseEvent
& event
)
193 if ( event
.GetEventType() == wxEVT_LEFT_DOWN
)
196 m_ptPosition
= event
.GetPosition();
198 else if ( event
.GetEventType() == wxEVT_LEFT_UP
)
203 else if ( event
.GetEventType() == wxEVT_MOTION
)
207 int dy
= m_ptPosition
.y
- event
.GetPosition().y
;
211 m_ptPosition
= event
.GetPosition();
213 wxSpinEvent
evtscroll( (dy
>= 0) ? wxEVT_SCROLL_LINEUP
:
214 wxEVT_SCROLL_LINEDOWN
,
216 evtscroll
.SetEventObject(this);
218 wxASSERT( m_spins
== 1 );
221 GetEventHandler()->ProcessEvent(evtscroll
);
229 void OnMouseCaptureLost(wxMouseCaptureLostEvent
& WXUNUSED(event
))
235 #endif // IS_MOTION_SPIN_SUPPORTED
238 WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl
,
243 // Destructor. It is useful to reset the global pointer in it.
244 wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
246 wxPG_EDITOR(SpinCtrl
) = NULL
;
249 // Create controls and initialize event handling.
250 wxPGWindowList
wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
251 const wxPoint
& pos
, const wxSize
& sz
) const
253 const int margin
= 1;
254 wxSize
butSz(18, sz
.y
);
255 wxSize
tcSz(sz
.x
- butSz
.x
- margin
, sz
.y
);
256 wxPoint
butPos(pos
.x
+ tcSz
.x
+ margin
, pos
.y
);
260 #if IS_MOTION_SPIN_SUPPORTED
261 if ( property
->GetAttributeAsLong(wxT("MotionSpin"), 0) )
263 wnd2
= new wxPGSpinButton();
268 wnd2
= new wxSpinButton();
274 wnd2
->Create( propgrid
->GetPanel(), wxPG_SUBID2
, butPos
, butSz
, wxSP_VERTICAL
);
276 wnd2
->SetRange( INT_MIN
, INT_MAX
);
279 wxWindow
* wnd1
= wxPGTextCtrlEditor::CreateControls(propgrid
, property
, pos
, tcSz
).m_primary
;
281 // Let's add validator to make sure only numbers can be entered
282 wxTextValidator
validator(wxFILTER_NUMERIC
, &m_tempString
);
283 wnd1
->SetValidator(validator
);
286 return wxPGWindowList(wnd1
, wnd2
);
289 // Control's events are redirected here
290 bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
291 wxWindow
* wnd
, wxEvent
& event
) const
293 int evtType
= event
.GetEventType();
296 bool bigStep
= false;
298 if ( evtType
== wxEVT_KEY_DOWN
)
300 wxKeyEvent
& keyEvent
= (wxKeyEvent
&)event
;
301 keycode
= keyEvent
.GetKeyCode();
303 if ( keycode
== WXK_UP
)
304 evtType
= wxEVT_SCROLL_LINEUP
;
305 else if ( keycode
== WXK_DOWN
)
306 evtType
= wxEVT_SCROLL_LINEDOWN
;
307 else if ( keycode
== WXK_PAGEUP
)
309 evtType
= wxEVT_SCROLL_LINEUP
;
312 else if ( keycode
== WXK_PAGEDOWN
)
314 evtType
= wxEVT_SCROLL_LINEDOWN
;
319 if ( evtType
== wxEVT_SCROLL_LINEUP
|| evtType
== wxEVT_SCROLL_LINEDOWN
)
321 #if IS_MOTION_SPIN_SUPPORTED
322 if ( property
->GetAttributeAsLong(wxT("MotionSpin"), 0) )
324 wxPGSpinButton
* spinButton
=
325 (wxPGSpinButton
*) propgrid
->GetEditorControlSecondary();
328 spins
= spinButton
->GetSpins();
333 // Can't use wnd since it might be clipper window
334 wxTextCtrl
* tc
= wxDynamicCast(propgrid
->GetEditorControl(), wxTextCtrl
);
339 s
= property
->GetValueAsString(wxPG_FULL_VALUE
);
341 int mode
= wxPG_PROPERTY_VALIDATION_SATURATE
;
343 if ( property
->GetAttributeAsLong(wxT("Wrap"), 0) )
344 mode
= wxPG_PROPERTY_VALIDATION_WRAP
;
346 if ( property
->GetValueType() == wxT("double") )
349 double step
= property
->GetAttributeAsDouble(wxT("Step"), 1.0);
352 if ( s
.ToDouble(&v_d
) )
357 step
*= (double) spins
;
359 if ( evtType
== wxEVT_SCROLL_LINEUP
) v_d
+= step
;
363 wxFloatProperty::DoValidation(property
, v_d
, NULL
, mode
);
365 wxPropertyGrid::DoubleToString(s
, v_d
, 6, true, NULL
);
375 wxLongLong_t step
= property
->GetAttributeAsLong(wxT("Step"), 1);
378 if ( s
.ToLongLong(&v_ll
, 10) )
385 if ( evtType
== wxEVT_SCROLL_LINEUP
) v_ll
+= step
;
389 wxIntProperty::DoValidation(property
, v_ll
, NULL
, mode
);
391 s
= wxLongLong(v_ll
).ToString();
401 int ip
= tc
->GetInsertionPoint();
402 int lp
= tc
->GetLastPosition();
404 tc
->SetInsertionPoint(ip
+(tc
->GetLastPosition()-lp
));
410 return wxPGTextCtrlEditor::OnEvent(propgrid
,property
,wnd
,event
);
413 #endif // wxUSE_SPINBTN
416 // -----------------------------------------------------------------------
417 // wxDatePickerCtrl-based property editor
418 // -----------------------------------------------------------------------
420 #if wxUSE_DATEPICKCTRL
423 #include "wx/datectrl.h"
424 #include "wx/dateevt.h"
426 class wxPGDatePickerCtrlEditor
: public wxPGEditor
428 DECLARE_DYNAMIC_CLASS(wxPGDatePickerCtrlEditor
)
430 virtual ~wxPGDatePickerCtrlEditor();
432 wxString
GetName() const;
433 virtual wxPGWindowList
CreateControls(wxPropertyGrid
* propgrid
,
434 wxPGProperty
* property
,
436 const wxSize
& size
) const;
437 virtual void UpdateControl( wxPGProperty
* property
, wxWindow
* wnd
) const;
438 virtual bool OnEvent( wxPropertyGrid
* propgrid
, wxPGProperty
* property
,
439 wxWindow
* wnd
, wxEvent
& event
) const;
440 virtual bool GetValueFromControl( wxVariant
& variant
, wxPGProperty
* property
, wxWindow
* wnd
) const;
441 virtual void SetValueToUnspecified( wxPGProperty
* WXUNUSED(property
), wxWindow
* wnd
) const;
445 WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(DatePickerCtrl
,
446 wxPGDatePickerCtrlEditor
,
450 wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
452 wxPG_EDITOR(DatePickerCtrl
) = NULL
;
455 wxPGWindowList
wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid
* propgrid
,
456 wxPGProperty
* property
,
458 const wxSize
& sz
) const
460 wxCHECK_MSG( property
->IsKindOf(CLASSINFO(wxDateProperty
)),
462 wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
464 wxDateProperty
* prop
= wxDynamicCast(property
, wxDateProperty
);
466 // Use two stage creation to allow cleaner display on wxMSW
467 wxDatePickerCtrl
* ctrl
= new wxDatePickerCtrl();
470 wxSize useSz
= wxDefaultSize
;
476 wxDateTime
dateValue(wxInvalidDateTime
);
478 wxVariant value
= prop
->GetValue();
479 if ( value
.GetType() == wxT("datetime") )
480 dateValue
= value
.GetDateTime();
482 ctrl
->Create(propgrid
->GetPanel(),
487 prop
->GetDatePickerStyle() | wxNO_BORDER
);
496 // Copies value from property to control
497 void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty
* property
,
498 wxWindow
* wnd
) const
500 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
501 wxASSERT( ctrl
&& ctrl
->IsKindOf(CLASSINFO(wxDatePickerCtrl
)) );
503 wxDateTime
dateValue(wxInvalidDateTime
);
504 wxVariant
v(property
->GetValue());
505 if ( v
.GetType() == wxT("datetime") )
506 dateValue
= v
.GetDateTime();
508 ctrl
->SetValue( dateValue
);
511 // Control's events are redirected here
512 bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid
* WXUNUSED(propgrid
),
513 wxPGProperty
* WXUNUSED(property
),
514 wxWindow
* WXUNUSED(wnd
),
515 wxEvent
& event
) const
517 if ( event
.GetEventType() == wxEVT_DATE_CHANGED
)
523 bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant
& variant
, wxPGProperty
* WXUNUSED(property
), wxWindow
* wnd
) const
525 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
526 wxASSERT( ctrl
&& ctrl
->IsKindOf(CLASSINFO(wxDatePickerCtrl
)) );
528 variant
= ctrl
->GetValue();
533 void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty
* property
,
534 wxWindow
* wnd
) const
536 wxDatePickerCtrl
* ctrl
= (wxDatePickerCtrl
*) wnd
;
537 wxASSERT( ctrl
&& ctrl
->IsKindOf(CLASSINFO(wxDatePickerCtrl
)) );
539 wxDateProperty
* prop
= wxDynamicCast(property
, wxDateProperty
);
543 int datePickerStyle
= prop
->GetDatePickerStyle();
544 if ( datePickerStyle
& wxDP_ALLOWNONE
)
545 ctrl
->SetValue(wxInvalidDateTime
);
549 #endif // wxUSE_DATEPICKCTRL
552 // -----------------------------------------------------------------------
554 // -----------------------------------------------------------------------
556 #include "wx/fontdlg.h"
557 #include "wx/fontenum.h"
560 // NB: Do not use wxS here since unlike wxT it doesn't translate to wxChar*
563 static const wxChar
* const gs_fp_es_family_labels
[] = {
564 wxT("Default"), wxT("Decorative"),
565 wxT("Roman"), wxT("Script"),
566 wxT("Swiss"), wxT("Modern"),
567 wxT("Teletype"), wxT("Unknown"),
571 static const long gs_fp_es_family_values
[] = {
572 wxFONTFAMILY_DEFAULT
, wxFONTFAMILY_DECORATIVE
,
573 wxFONTFAMILY_ROMAN
, wxFONTFAMILY_SCRIPT
,
574 wxFONTFAMILY_SWISS
, wxFONTFAMILY_MODERN
,
575 wxFONTFAMILY_TELETYPE
, wxFONTFAMILY_UNKNOWN
578 static const wxChar
* const gs_fp_es_style_labels
[] = {
585 static const long gs_fp_es_style_values
[] = {
591 static const wxChar
* const gs_fp_es_weight_labels
[] = {
598 static const long gs_fp_es_weight_values
[] = {
604 // Class body is in advprops.h
607 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty
,wxPGProperty
,
608 wxFont
,const wxFont
&,TextCtrlAndButton
)
611 wxFontProperty::wxFontProperty( const wxString
& label
, const wxString
& name
,
612 const wxFont
& value
)
613 : wxPGProperty(label
,name
)
615 SetValue(WXVARIANT(value
));
617 // Initialize font family choices list
618 if ( !wxPGGlobalVars
->m_fontFamilyChoices
)
620 wxArrayString faceNames
= wxFontEnumerator::GetFacenames();
624 wxPGGlobalVars
->m_fontFamilyChoices
= new wxPGChoices(faceNames
);
627 wxString
emptyString(wxEmptyString
);
632 AddPrivateChild( new wxIntProperty( _("Point Size"),
633 wxS("Point Size"),(long)font
.GetPointSize() ) );
635 wxString faceName
= font
.GetFaceName();
636 // If font was not in there, add it now
637 if ( faceName
.length() &&
638 wxPGGlobalVars
->m_fontFamilyChoices
->Index(faceName
) == wxNOT_FOUND
)
639 wxPGGlobalVars
->m_fontFamilyChoices
->AddAsSorted(faceName
);
641 wxPGProperty
* p
= new wxEnumProperty(_("Face Name"), wxS("Face Name"),
642 *wxPGGlobalVars
->m_fontFamilyChoices
);
644 p
->SetValueFromString(faceName
, wxPG_FULL_VALUE
);
646 AddPrivateChild( p
);
648 AddPrivateChild( new wxEnumProperty(_("Style"), wxS("Style"),
649 gs_fp_es_style_labels
,gs_fp_es_style_values
,
652 AddPrivateChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
653 gs_fp_es_weight_labels
,gs_fp_es_weight_values
,
656 AddPrivateChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
657 font
.GetUnderlined()) );
659 AddPrivateChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
660 gs_fp_es_family_labels
,gs_fp_es_family_values
,
664 wxFontProperty::~wxFontProperty() { }
666 void wxFontProperty::OnSetValue()
673 m_value
<< *wxNORMAL_FONT
;
677 wxString
wxFontProperty::ValueToString( wxVariant
& value
,
680 return wxPGProperty::ValueToString(value
, argFlags
);
683 bool wxFontProperty::OnEvent( wxPropertyGrid
* propgrid
, wxWindow
* WXUNUSED(primary
),
686 if ( propgrid
->IsMainButtonEvent(event
) )
688 // Update value from last minute changes
689 wxVariant useValue
= propgrid
->GetUncommittedPropertyValue();
694 if ( useValue
.GetType() == wxS("wxFont") )
697 data
.SetInitialFont( font
);
698 data
.SetColour(*wxBLACK
);
700 wxFontDialog
dlg(propgrid
, data
);
701 if ( dlg
.ShowModal() == wxID_OK
)
703 propgrid
->EditorsValueWasModified();
706 variant
<< dlg
.GetFontData().GetChosenFont();
707 SetValueInEvent( variant
);
714 void wxFontProperty::RefreshChildren()
716 if ( !GetChildCount() ) return;
719 Item(0)->SetValue( (long)font
.GetPointSize() );
720 Item(1)->SetValueFromString( font
.GetFaceName(), wxPG_FULL_VALUE
);
721 Item(2)->SetValue( (long)font
.GetStyle() );
722 Item(3)->SetValue( (long)font
.GetWeight() );
723 Item(4)->SetValue( font
.GetUnderlined() );
724 Item(5)->SetValue( (long)font
.GetFamily() );
727 wxVariant
wxFontProperty::ChildChanged( wxVariant
& thisValue
,
729 wxVariant
& childValue
) const
736 font
.SetPointSize( childValue
.GetLong() );
741 int faceIndex
= childValue
.GetLong();
743 if ( faceIndex
>= 0 )
744 faceName
= wxPGGlobalVars
->m_fontFamilyChoices
->GetLabel(faceIndex
);
746 font
.SetFaceName( faceName
);
750 int st
= childValue
.GetLong();
751 if ( st
!= wxFONTSTYLE_NORMAL
&&
752 st
!= wxFONTSTYLE_SLANT
&&
753 st
!= wxFONTSTYLE_ITALIC
)
754 st
= wxFONTWEIGHT_NORMAL
;
759 int wt
= childValue
.GetLong();
760 if ( wt
!= wxFONTWEIGHT_NORMAL
&&
761 wt
!= wxFONTWEIGHT_LIGHT
&&
762 wt
!= wxFONTWEIGHT_BOLD
)
763 wt
= wxFONTWEIGHT_NORMAL
;
764 font
.SetWeight( wt
);
768 font
.SetUnderlined( childValue
.GetBool() );
772 int fam
= childValue
.GetLong();
773 if ( fam
< wxDEFAULT
||
776 font
.SetFamily( fam
);
779 wxVariant newVariant
;
785 wxSize wxFontProperty::OnMeasureImage() const
787 return wxSize(-1,-1);
790 void wxFontProperty::OnCustomPaint(wxDC& dc,
792 wxPGPaintData& paintData)
795 if ( paintData.m_choiceItem >= 0 )
796 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
798 drawFace = m_value_wxFont.GetFaceName();
800 if ( drawFace.length() )
802 // Draw the background
803 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
804 //dc.SetBrush( *wxWHITE_BRUSH );
805 //dc.SetPen( *wxMEDIUM_GREY_PEN );
806 dc.DrawRectangle( rect );
808 wxFont oldFont = dc.GetFont();
809 wxFont drawFont(oldFont.GetPointSize(),
810 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
811 dc.SetFont(drawFont);
813 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
814 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
820 // No file - just draw a white box
821 dc.SetBrush ( *wxWHITE_BRUSH );
822 dc.DrawRectangle ( rect );
828 // -----------------------------------------------------------------------
829 // wxSystemColourProperty
830 // -----------------------------------------------------------------------
832 // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
833 #define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
835 #include "wx/colordlg.h"
837 //#define wx_cp_es_syscolours_len 25
838 static const wxChar
* const gs_cp_es_syscolour_labels
[] = {
841 wxT("ActiveCaption"),
843 wxT("ButtonHighlight"),
852 wxT("HighlightText"),
853 wxT("InactiveBorder"),
854 wxT("InactiveCaption"),
855 wxT("InactiveCaptionText"),
867 static const long gs_cp_es_syscolour_values
[] = {
868 wxSYS_COLOUR_APPWORKSPACE
,
869 wxSYS_COLOUR_ACTIVEBORDER
,
870 wxSYS_COLOUR_ACTIVECAPTION
,
871 wxSYS_COLOUR_BTNFACE
,
872 wxSYS_COLOUR_BTNHIGHLIGHT
,
873 wxSYS_COLOUR_BTNSHADOW
,
874 wxSYS_COLOUR_BTNTEXT
,
875 wxSYS_COLOUR_CAPTIONTEXT
,
876 wxSYS_COLOUR_3DDKSHADOW
,
877 wxSYS_COLOUR_3DLIGHT
,
878 wxSYS_COLOUR_BACKGROUND
,
879 wxSYS_COLOUR_GRAYTEXT
,
880 wxSYS_COLOUR_HIGHLIGHT
,
881 wxSYS_COLOUR_HIGHLIGHTTEXT
,
882 wxSYS_COLOUR_INACTIVEBORDER
,
883 wxSYS_COLOUR_INACTIVECAPTION
,
884 wxSYS_COLOUR_INACTIVECAPTIONTEXT
,
886 wxSYS_COLOUR_SCROLLBAR
,
888 wxSYS_COLOUR_INFOTEXT
,
890 wxSYS_COLOUR_WINDOWFRAME
,
891 wxSYS_COLOUR_WINDOWTEXT
,
896 IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue
, WXDLLIMPEXP_PROPGRID
)
899 // Class body is in advprops.h
901 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty
,wxEnumProperty
,
902 wxColourPropertyValue
,const wxColourPropertyValue
&,Choice
)
905 void wxSystemColourProperty::Init( int type
, const wxColour
& colour
)
907 wxColourPropertyValue cpv
;
910 cpv
.Init( type
, colour
);
912 cpv
.Init( type
, *wxWHITE
);
914 m_flags
|= wxPG_PROP_STATIC_CHOICES
; // Colour selection cannot be changed.
922 static wxPGChoices gs_wxSystemColourProperty_choicesCache
;
925 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
926 const wxColourPropertyValue
& value
)
927 : wxEnumProperty( label
,
929 gs_cp_es_syscolour_labels
,
930 gs_cp_es_syscolour_values
,
931 &gs_wxSystemColourProperty_choicesCache
)
934 Init( value
.m_type
, value
.m_colour
);
936 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
940 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
941 const wxChar
* const* labels
, const long* values
, wxPGChoices
* choicesCache
,
942 const wxColourPropertyValue
& value
)
943 : wxEnumProperty( label
, name
, labels
, values
, choicesCache
)
946 Init( value
.m_type
, value
.m_colour
);
948 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
952 wxSystemColourProperty::wxSystemColourProperty( const wxString
& label
, const wxString
& name
,
953 const wxChar
* const* labels
, const long* values
, wxPGChoices
* choicesCache
,
954 const wxColour
& value
)
955 : wxEnumProperty( label
, name
, labels
, values
, choicesCache
)
958 Init( wxPG_COLOUR_CUSTOM
, value
);
960 Init( wxPG_COLOUR_CUSTOM
, *wxWHITE
);
964 wxSystemColourProperty::~wxSystemColourProperty() { }
967 wxColourPropertyValue
wxSystemColourProperty::GetVal( const wxVariant
* pVariant
) const
972 if ( pVariant
->IsNull() )
973 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED
, wxColour());
975 if ( pVariant
->GetType() == wxS("wxColourPropertyValue") )
977 wxColourPropertyValue v
;
983 bool variantProcessed
= true;
985 if ( pVariant
->GetType() == wxS("wxColour*") )
987 wxColour
* pCol
= wxStaticCast(pVariant
->GetWxObjectPtr(), wxColour
);
990 else if ( pVariant
->GetType() == wxS("wxColour") )
994 else if ( pVariant
->GetType() == wxArrayInt_VariantType
)
996 // This code is mostly needed for wxPython bindings, which
997 // may offer tuple of integers as colour value.
1001 if ( arr
.size() >= 3 )
1009 if ( arr
.size() >= 4 )
1012 col
= wxColour(r
, g
, b
, a
);
1016 variantProcessed
= false;
1021 variantProcessed
= false;
1024 if ( !variantProcessed
)
1025 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED
, wxColour());
1027 wxColourPropertyValue
v2( wxPG_COLOUR_CUSTOM
, col
);
1029 int colInd
= ColToInd(col
);
1030 if ( colInd
!= wxNOT_FOUND
)
1036 wxVariant
wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue
& v
) const
1043 int wxSystemColourProperty::ColToInd( const wxColour
& colour
) const
1046 size_t i_max
= m_choices
.GetCount();
1048 if ( !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1051 for ( i
=0; i
<i_max
; i
++ )
1053 int ind
= m_choices
[i
].GetValue();
1055 if ( colour
== GetColour(ind
) )
1057 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1058 GetClassName(),GetLabel().c_str(),
1059 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1060 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1067 void wxSystemColourProperty::OnSetValue()
1069 // Convert from generic wxobject ptr to wxPGVariantDataColour
1070 if ( m_value
.GetType() == wxS("wxColour*") )
1072 wxColour
* pCol
= wxStaticCast(m_value
.GetWxObjectPtr(), wxColour
);
1076 wxColourPropertyValue val
= GetVal(&m_value
);
1078 if ( val
.m_type
== wxPG_COLOUR_UNSPECIFIED
)
1086 if ( val
.m_type
< wxPG_COLOUR_WEB_BASE
)
1087 val
.m_colour
= GetColour( val
.m_type
);
1089 m_value
= TranslateVal(val
);
1092 int ind
= wxNOT_FOUND
;
1094 if ( m_value
.GetType() == wxS("wxColourPropertyValue") )
1096 wxColourPropertyValue cpv
;
1098 wxColour col
= cpv
.m_colour
;
1102 SetValueToUnspecified();
1103 SetIndex(wxNOT_FOUND
);
1107 if ( cpv
.m_type
< wxPG_COLOUR_WEB_BASE
||
1108 (m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1110 ind
= GetIndexForValue(cpv
.m_type
);
1114 cpv
.m_type
= wxPG_COLOUR_CUSTOM
;
1115 ind
= GetCustomColourIndex();
1125 SetValueToUnspecified();
1126 SetIndex(wxNOT_FOUND
);
1130 ind
= ColToInd(col
);
1132 if ( ind
== wxNOT_FOUND
&&
1133 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1134 ind
= GetCustomColourIndex();
1141 wxColour
wxSystemColourProperty::GetColour( int index
) const
1143 return wxSystemSettings::GetColour( (wxSystemColour
)index
);
1146 wxString
wxSystemColourProperty::ColourToString( const wxColour
& col
, int index
) const
1148 if ( index
== wxNOT_FOUND
)
1149 return wxString::Format(wxT("(%i,%i,%i)"),
1154 return m_choices
.GetLabel(index
);
1157 wxString
wxSystemColourProperty::ValueToString( wxVariant
& value
,
1158 int argFlags
) const
1160 wxColourPropertyValue val
= GetVal(&value
);
1164 if ( argFlags
& wxPG_VALUE_IS_CURRENT
)
1166 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1167 // but we should use it whenever possible.
1170 // If custom colour was selected, use invalid index, so that
1171 // ColourToString() will return properly formatted colour text.
1172 if ( index
== GetCustomColourIndex() &&
1173 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1174 index
= wxNOT_FOUND
;
1178 index
= m_choices
.Index(val
.m_type
);
1181 return ColourToString(val
.m_colour
, index
);
1185 wxSize
wxSystemColourProperty::OnMeasureImage( int ) const
1187 return wxPG_DEFAULT_IMAGE_SIZE
;
1191 int wxSystemColourProperty::GetCustomColourIndex() const
1193 return m_choices
.GetCount() - 1;
1197 bool wxSystemColourProperty::QueryColourFromUser( wxVariant
& variant
) const
1199 wxASSERT( m_value
.GetType() != wxPG_VARIANT_TYPE_STRING
);
1202 wxPropertyGrid
* propgrid
= GetGrid();
1203 wxASSERT( propgrid
);
1205 // Must only occur when user triggers event
1206 if ( !(propgrid
->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT
) )
1209 wxColourPropertyValue val
= GetVal();
1211 val
.m_type
= wxPG_COLOUR_CUSTOM
;
1214 data
.SetChooseFull(true);
1215 data
.SetColour(val
.m_colour
);
1217 for ( i
= 0; i
< 16; i
++)
1219 wxColour
colour(i
*16, i
*16, i
*16);
1220 data
.SetCustomColour(i
, colour
);
1223 wxColourDialog
dialog(propgrid
, &data
);
1224 if ( dialog
.ShowModal() == wxID_OK
)
1226 wxColourData retData
= dialog
.GetColourData();
1227 val
.m_colour
= retData
.GetColour();
1229 variant
= DoTranslateVal(val
);
1231 SetValueInEvent(variant
);
1240 bool wxSystemColourProperty::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
1243 int type
= m_choices
.GetValue(index
);
1245 if ( type
== wxPG_COLOUR_CUSTOM
)
1247 QueryColourFromUser(variant
);
1251 variant
= TranslateVal( type
, GetColour(type
) );
1257 // Need to do some extra event handling.
1258 bool wxSystemColourProperty::OnEvent( wxPropertyGrid
* propgrid
,
1259 wxWindow
* WXUNUSED(primary
),
1262 bool askColour
= false;
1264 if ( propgrid
->IsMainButtonEvent(event
) )
1266 // We need to handle button click in case editor has been
1267 // switched to one that has wxButton as well.
1270 else if ( event
.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED
)
1272 // Must override index detection since at this point GetIndex()
1273 // will return old value.
1274 wxOwnerDrawnComboBox
* cb
=
1275 static_cast<wxOwnerDrawnComboBox
*>(propgrid
->GetEditorControl());
1279 int index
= cb
->GetSelection();
1281 if ( index
== GetCustomColourIndex() &&
1282 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1287 if ( askColour
&& !propgrid
->WasValueChangedInEvent() )
1290 if ( QueryColourFromUser(variant
) )
1296 /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1299 virtual void Render( wxDC& dc, const wxRect& rect,
1300 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1301 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1303 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1304 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1306 dc.SetPen(*wxBLACK_PEN);
1308 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1312 const wxArrayInt& values = prop->GetValues();
1313 if ( values.GetChildCount() )
1314 colInd = values[item];
1317 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1319 else if ( !prop->IsValueUnspecified() )
1320 dc.SetBrush( prop->GetVal().m_colour );
1322 dc.SetBrush( *wxWHITE );
1324 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1325 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1326 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1327 imageRect.width, imageRect.height );
1331 text = property->GetValueAsString();
1333 text = property->GetChoiceString(item);
1334 DrawText( dc, rect, imageRect.width, text );
1339 wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1341 wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1344 return &g_wxPGColourPropertyRenderer;
1345 return wxEnumProperty::GetCellRenderer(column);
1348 void wxSystemColourProperty::OnCustomPaint( wxDC
& dc
, const wxRect
& rect
,
1349 wxPGPaintData
& paintdata
)
1353 if ( paintdata
.m_choiceItem
>= 0 &&
1354 paintdata
.m_choiceItem
< (int)m_choices
.GetCount() &&
1355 (paintdata
.m_choiceItem
!= GetCustomColourIndex() ||
1356 m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1358 int colInd
= m_choices
[paintdata
.m_choiceItem
].GetValue();
1359 col
= GetColour( colInd
);
1361 else if ( !IsValueUnspecified() )
1363 col
= GetVal().m_colour
;
1369 dc
.DrawRectangle(rect
);
1374 bool wxSystemColourProperty::StringToValue( wxVariant
& value
, const wxString
& text
, int argFlags
) const
1376 wxString
custColName(m_choices
.GetLabel(GetCustomColourIndex()));
1377 wxString
colStr(text
);
1381 wxColour customColour
;
1382 bool conversionSuccess
= false;
1384 if ( colStr
!= custColName
)
1386 // Convert (R,G,B) to rgb(R,G,B)
1387 if ( colStr
.Find(wxS("(")) == 0 )
1389 colStr
= wxS("rgb") + colStr
;
1392 conversionSuccess
= customColour
.Set(colStr
);
1395 if ( !conversionSuccess
&& m_choices
.GetCount() &&
1396 !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) &&
1397 colStr
== custColName
)
1399 if ( !(argFlags
& wxPG_EDITABLE_VALUE
))
1401 // This really should not occurr...
1407 QueryColourFromUser(value
);
1411 wxColourPropertyValue val
;
1415 if ( !conversionSuccess
)
1417 // Try predefined colour first
1418 bool res
= wxEnumProperty::StringToValue(value
,
1421 if ( res
&& GetIndex() >= 0 )
1423 val
.m_type
= GetIndex();
1424 if ( val
.m_type
< m_choices
.GetCount() )
1425 val
.m_type
= m_choices
[val
.m_type
].GetValue();
1427 // Get proper colour for type.
1428 val
.m_colour
= GetColour(val
.m_type
);
1435 val
.m_type
= wxPG_COLOUR_CUSTOM
;
1436 val
.m_colour
= customColour
;
1446 value
= DoTranslateVal(val
);
1453 bool wxSystemColourProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
1455 if ( name
== wxPG_COLOUR_ALLOW_CUSTOM
)
1457 int ival
= value
.GetLong();
1459 if ( ival
&& (m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1461 // Show custom choice
1462 m_choices
.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM
);
1463 m_flags
&= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR
);
1465 else if ( !ival
&& !(m_flags
& wxPG_PROP_HIDE_CUSTOM_COLOUR
) )
1467 // Hide custom choice
1468 m_choices
.RemoveAt(GetCustomColourIndex());
1469 m_flags
|= wxPG_PROP_HIDE_CUSTOM_COLOUR
;
1477 // -----------------------------------------------------------------------
1479 // -----------------------------------------------------------------------
1481 static const wxChar
* const gs_cp_es_normcolour_labels
[] = {
1501 (const wxChar
*) NULL
1504 static const unsigned long gs_cp_es_normcolour_colours
[] = {
1506 wxPG_COLOUR(128,0,0),
1507 wxPG_COLOUR(0,0,128),
1508 wxPG_COLOUR(128,0,128),
1509 wxPG_COLOUR(0,128,128),
1510 wxPG_COLOUR(128,128,128),
1511 wxPG_COLOUR(0,128,0),
1512 wxPG_COLOUR(128,128,0),
1513 wxPG_COLOUR(166,124,81),
1514 wxPG_COLOUR(0,0,255),
1515 wxPG_COLOUR(255,0,255),
1516 wxPG_COLOUR(255,0,0),
1517 wxPG_COLOUR(247,148,28),
1518 wxPG_COLOUR(192,192,192),
1519 wxPG_COLOUR(0,255,0),
1520 wxPG_COLOUR(0,255,255),
1521 wxPG_COLOUR(255,255,0),
1522 wxPG_COLOUR(255,255,255),
1526 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty
, wxSystemColourProperty
,
1527 wxColour
, const wxColour
&, TextCtrlAndButton
)
1529 static wxPGChoices gs_wxColourProperty_choicesCache
;
1531 wxColourProperty::wxColourProperty( const wxString
& label
,
1532 const wxString
& name
,
1533 const wxColour
& value
)
1534 : wxSystemColourProperty(label
, name
, gs_cp_es_normcolour_labels
,
1536 &gs_wxColourProperty_choicesCache
, value
)
1540 m_flags
|= wxPG_PROP_TRANSLATE_CUSTOM
;
1543 wxColourProperty::~wxColourProperty()
1547 void wxColourProperty::Init( wxColour colour
)
1554 int ind
= ColToInd(colour
);
1556 ind
= m_choices
.GetCount() - 1;
1560 wxString
wxColourProperty::ValueToString( wxVariant
& value
,
1561 int argFlags
) const
1563 const wxPGEditor
* editor
= GetEditorClass();
1564 if ( editor
!= wxPGEditor_Choice
&&
1565 editor
!= wxPGEditor_ChoiceAndButton
&&
1566 editor
!= wxPGEditor_ComboBox
)
1567 argFlags
|= wxPG_PROPERTY_SPECIFIC
;
1569 return wxSystemColourProperty::ValueToString(value
, argFlags
);
1572 wxColour
wxColourProperty::GetColour( int index
) const
1574 return gs_cp_es_normcolour_colours
[m_choices
.GetValue(index
)];
1577 wxVariant
wxColourProperty::DoTranslateVal( wxColourPropertyValue
& v
) const
1580 variant
<< v
.m_colour
;
1584 // -----------------------------------------------------------------------
1586 // -----------------------------------------------------------------------
1588 #define wxPG_CURSOR_IMAGE_WIDTH 32
1590 #define NUM_CURSORS 28
1592 //#define wx_cp_es_syscursors_len 28
1593 static const wxChar
* const gs_cp_es_syscursors_labels
[NUM_CURSORS
+1] = {
1605 wxT("Middle Button"),
1611 wxT("Question Arrow"),
1612 wxT("Right Button"),
1613 wxT("Sizing NE-SW"),
1615 wxT("Sizing NW-SE"),
1622 (const wxChar
*) NULL
1625 static const long gs_cp_es_syscursors_values
[NUM_CURSORS
] = {
1628 wxCURSOR_RIGHT_ARROW
,
1635 wxCURSOR_LEFT_BUTTON
,
1637 wxCURSOR_MIDDLE_BUTTON
,
1639 wxCURSOR_PAINT_BRUSH
,
1641 wxCURSOR_POINT_LEFT
,
1642 wxCURSOR_POINT_RIGHT
,
1643 wxCURSOR_QUESTION_ARROW
,
1644 wxCURSOR_RIGHT_BUTTON
,
1656 IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty
, wxEnumProperty
)
1658 wxCursorProperty::wxCursorProperty( const wxString
& label
, const wxString
& name
,
1660 : wxEnumProperty( label
,
1662 gs_cp_es_syscursors_labels
,
1663 gs_cp_es_syscursors_values
,
1666 m_flags
|= wxPG_PROP_STATIC_CHOICES
; // Cursor selection cannot be changed.
1669 wxCursorProperty::~wxCursorProperty()
1673 wxSize
wxCursorProperty::OnMeasureImage( int item
) const
1675 #if wxPG_CAN_DRAW_CURSOR
1676 if ( item
!= -1 && item
< NUM_CURSORS
)
1677 return wxSize(wxPG_CURSOR_IMAGE_WIDTH
,wxPG_CURSOR_IMAGE_WIDTH
);
1684 #if wxPG_CAN_DRAW_CURSOR
1686 void wxCursorProperty::OnCustomPaint( wxDC
& dc
,
1688 wxPGPaintData
& paintdata
)
1691 dc
.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
) );
1693 if ( paintdata
.m_choiceItem
>= 0 )
1695 dc
.DrawRectangle( rect
);
1697 if ( paintdata
.m_choiceItem
< NUM_CURSORS
)
1699 wxStockCursor cursorIndex
=
1700 (wxStockCursor
) gs_cp_es_syscursors_values
[paintdata
.m_choiceItem
];
1703 if ( cursorIndex
== wxCURSOR_NONE
)
1704 cursorIndex
= wxCURSOR_ARROW
;
1706 wxCursor
cursor( cursorIndex
);
1709 HDC hDc
= (HDC
)((const wxMSWDCImpl
*)dc
.GetImpl())->GetHDC();
1713 (HICON
)cursor
.GetHandle(),
1718 #if !defined(__WXWINCE__)
1719 DI_COMPAT
| DI_DEFAULTSIZE
|
1730 void wxCursorProperty::OnCustomPaint( wxDC
&, const wxRect
&, wxPGPaintData
& ) { }
1731 /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1733 return wxEnumProperty::GetCellRenderer(column);
1737 // -----------------------------------------------------------------------
1738 // wxImageFileProperty
1739 // -----------------------------------------------------------------------
1743 const wxString
& wxPGGetDefaultImageWildcard()
1745 // Form the wildcard, if not done yet
1746 if ( !wxPGGlobalVars
->m_pDefaultImageWildcard
.length() )
1751 // TODO: This section may require locking (using global).
1753 wxList
& handlers
= wxImage::GetHandlers();
1755 wxList::iterator node
;
1757 // Let's iterate over the image handler list.
1758 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1759 for ( node
= handlers
.begin(); node
!= handlers
.end(); ++node
)
1761 wxImageHandler
*handler
= (wxImageHandler
*)*node
;
1763 wxString ext_lo
= handler
->GetExtension();
1764 wxString ext_up
= ext_lo
.Upper();
1766 str
.append( ext_up
);
1767 str
.append( wxT(" files (*.") );
1768 str
.append( ext_up
);
1769 str
.append( wxT(")|*.") );
1770 str
.append( ext_lo
);
1771 str
.append( wxT("|") );
1774 str
.append ( wxT("All files (*.*)|*.*") );
1776 wxPGGlobalVars
->m_pDefaultImageWildcard
= str
;
1779 return wxPGGlobalVars
->m_pDefaultImageWildcard
;
1782 IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty
, wxFileProperty
)
1784 wxImageFileProperty::wxImageFileProperty( const wxString
& label
, const wxString
& name
,
1785 const wxString
& value
)
1786 : wxFileProperty(label
,name
,value
)
1788 SetAttribute( wxPG_FILE_WILDCARD
, wxPGGetDefaultImageWildcard() );
1794 wxImageFileProperty::~wxImageFileProperty()
1802 void wxImageFileProperty::OnSetValue()
1804 wxFileProperty::OnSetValue();
1808 wxDELETE(m_pBitmap
);
1810 wxFileName filename
= GetFileName();
1812 // Create the image thumbnail
1813 if ( filename
.FileExists() )
1815 m_pImage
= new wxImage( filename
.GetFullPath() );
1819 wxSize
wxImageFileProperty::OnMeasureImage( int ) const
1821 return wxPG_DEFAULT_IMAGE_SIZE
;
1824 void wxImageFileProperty::OnCustomPaint( wxDC
& dc
,
1828 if ( m_pBitmap
|| (m_pImage
&& m_pImage
->Ok() ) )
1830 // Draw the thumbnail
1832 // Create the bitmap here because required size is not known in OnSetValue().
1835 m_pImage
->Rescale( rect
.width
, rect
.height
);
1836 m_pBitmap
= new wxBitmap( *m_pImage
);
1840 dc
.DrawBitmap( *m_pBitmap
, rect
.x
, rect
.y
, false );
1844 // No file - just draw a white box
1845 dc
.SetBrush( *wxWHITE_BRUSH
);
1846 dc
.DrawRectangle ( rect
);
1850 #endif // wxUSE_IMAGE
1852 // -----------------------------------------------------------------------
1853 // wxMultiChoiceProperty
1854 // -----------------------------------------------------------------------
1858 #include "wx/choicdlg.h"
1860 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty
,wxPGProperty
,
1861 wxArrayInt
,const wxArrayInt
&,TextCtrlAndButton
)
1863 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1864 const wxString
& name
,
1865 const wxPGChoices
& choices
,
1866 const wxArrayString
& value
)
1867 : wxPGProperty(label
,name
)
1869 m_choices
.Assign(choices
);
1873 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1874 const wxString
& name
,
1875 const wxArrayString
& strings
,
1876 const wxArrayString
& value
)
1877 : wxPGProperty(label
,name
)
1879 m_choices
.Set(strings
);
1883 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString
& label
,
1884 const wxString
& name
,
1885 const wxArrayString
& value
)
1886 : wxPGProperty(label
,name
)
1888 wxArrayString strings
;
1889 m_choices
.Set(strings
);
1893 wxMultiChoiceProperty::~wxMultiChoiceProperty()
1897 void wxMultiChoiceProperty::OnSetValue()
1899 GenerateValueAsString(m_value
, &m_display
);
1902 wxString
wxMultiChoiceProperty::ValueToString( wxVariant
& value
,
1903 int argFlags
) const
1905 // If possible, use cached string
1906 if ( argFlags
& wxPG_VALUE_IS_CURRENT
)
1910 GenerateValueAsString(value
, &s
);
1914 void wxMultiChoiceProperty::GenerateValueAsString( wxVariant
& value
,
1915 wxString
* target
) const
1917 wxArrayString strings
;
1919 if ( value
.GetType() == wxPG_VARIANT_TYPE_ARRSTRING
)
1920 strings
= value
.GetArrayString();
1922 wxString
& tempStr
= *target
;
1924 unsigned int itemCount
= strings
.size();
1929 tempStr
.append( wxT("\"") );
1931 for ( i
= 0; i
< itemCount
; i
++ )
1933 tempStr
.append( strings
[i
] );
1934 tempStr
.append( wxT("\"") );
1935 if ( i
< (itemCount
-1) )
1936 tempStr
.append ( wxT(" \"") );
1940 wxArrayInt
wxMultiChoiceProperty::GetValueAsIndices() const
1942 wxVariant variant
= GetValue();
1943 const wxArrayInt
& valueArr
= wxArrayIntRefFromVariant(variant
);
1946 // Translate values to string indices.
1947 wxArrayInt selections
;
1949 if ( !m_choices
.IsOk() || !m_choices
.GetCount() || !(&valueArr
) )
1951 for ( i
=0; i
<valueArr
.size(); i
++ )
1956 for ( i
=0; i
<valueArr
.size(); i
++ )
1958 int sIndex
= m_choices
.Index(valueArr
[i
]);
1960 selections
.Add(sIndex
);
1967 bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid
* propgrid
,
1968 wxWindow
* WXUNUSED(primary
),
1971 if ( propgrid
->IsMainButtonEvent(event
) )
1974 wxVariant useValue
= propgrid
->GetUncommittedPropertyValue();
1976 wxArrayString labels
= m_choices
.GetLabels();
1977 unsigned int choiceCount
;
1979 if ( m_choices
.IsOk() )
1980 choiceCount
= m_choices
.GetCount();
1984 // launch editor dialog
1985 wxMultiChoiceDialog
dlg( propgrid
,
1986 _("Make a selection:"),
1989 choiceCount
?&labels
[0]:NULL
,
1990 wxCHOICEDLG_STYLE
);
1992 dlg
.Move( propgrid
->GetGoodEditorDialogPosition(this,dlg
.GetSize()) );
1994 wxArrayString strings
= useValue
.GetArrayString();
1995 wxArrayString extraStrings
;
1997 dlg
.SetSelections(m_choices
.GetIndicesForStrings(strings
, &extraStrings
));
1999 if ( dlg
.ShowModal() == wxID_OK
&& choiceCount
)
2001 int userStringMode
= GetAttributeAsLong(wxT("UserStringMode"), 0);
2003 wxArrayInt arrInt
= dlg
.GetSelections();
2007 // Strings that were not in list of choices
2008 wxArrayString value
;
2010 // Translate string indices to strings
2013 if ( userStringMode
== 1 )
2015 for (n
=0;n
<extraStrings
.size();n
++)
2016 value
.push_back(extraStrings
[n
]);
2020 for ( i
=0; i
<arrInt
.size(); i
++ )
2021 value
.Add(m_choices
.GetLabel(arrInt
.Item(i
)));
2023 if ( userStringMode
== 2 )
2025 for (n
=0;n
<extraStrings
.size();n
++)
2026 value
.push_back(extraStrings
[n
]);
2029 variant
= WXVARIANT(value
);
2031 SetValueInEvent(variant
);
2039 bool wxMultiChoiceProperty::StringToValue( wxVariant
& variant
, const wxString
& text
, int ) const
2043 int userStringMode
= GetAttributeAsLong(wxT("UserStringMode"), 0);
2045 WX_PG_TOKENIZER2_BEGIN(text
,wxT('"'))
2046 if ( userStringMode
> 0 || (m_choices
.IsOk() && m_choices
.Index( token
) != wxNOT_FOUND
) )
2048 WX_PG_TOKENIZER2_END()
2050 wxVariant
v( WXVARIANT(arr
) );
2056 #endif // wxUSE_CHOICEDLG
2059 // -----------------------------------------------------------------------
2061 // -----------------------------------------------------------------------
2066 #if wxUSE_DATEPICKCTRL
2067 #define dtCtrl DatePickerCtrl
2069 #define dtCtrl TextCtrl
2072 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty
,
2079 wxString
wxDateProperty::ms_defaultDateFormat
;
2082 wxDateProperty::wxDateProperty( const wxString
& label
,
2083 const wxString
& name
,
2084 const wxDateTime
& value
)
2085 : wxPGProperty(label
,name
)
2087 //wxPGRegisterDefaultValueType(wxDateTime)
2089 #if wxUSE_DATEPICKCTRL
2090 wxPGRegisterEditorClass(DatePickerCtrl
);
2092 m_dpStyle
= wxDP_DEFAULT
| wxDP_SHOWCENTURY
;
2100 wxDateProperty::~wxDateProperty()
2104 void wxDateProperty::OnSetValue()
2107 // Convert invalid dates to unspecified value
2108 if ( m_value
.GetType() == wxT("datetime") )
2110 if ( !m_value
.GetDateTime().IsValid() )
2115 bool wxDateProperty::StringToValue( wxVariant
& variant
, const wxString
& text
,
2116 int WXUNUSED(argFlags
) ) const
2120 // FIXME: do we really want to return true from here if only part of the
2121 // string was parsed?
2122 const char* c
= dt
.ParseFormat(text
);
2133 wxString
wxDateProperty::ValueToString( wxVariant
& value
,
2134 int argFlags
) const
2136 const wxChar
* format
= (const wxChar
*) NULL
;
2138 wxDateTime dateTime
= value
.GetDateTime();
2140 if ( !dateTime
.IsValid() )
2141 return wxT("Invalid");
2143 if ( !ms_defaultDateFormat
.length() )
2145 #if wxUSE_DATEPICKCTRL
2146 bool showCentury
= m_dpStyle
& wxDP_SHOWCENTURY
? true : false;
2148 bool showCentury
= true;
2150 ms_defaultDateFormat
= DetermineDefaultDateFormat( showCentury
);
2153 if ( m_format
.length() &&
2154 !(argFlags
& wxPG_FULL_VALUE
) )
2155 format
= m_format
.c_str();
2157 // Determine default from locale
2158 // NB: This is really simple stuff, but can't figure anything
2159 // better without proper support in wxLocale
2161 format
= ms_defaultDateFormat
.c_str();
2163 return dateTime
.Format(format
);
2166 wxString
wxDateProperty::DetermineDefaultDateFormat( bool showCentury
)
2168 // This code is basicly copied from datectlg.cpp's SetFormat
2173 dt
.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2174 wxString
str(dt
.Format(wxT("%x")));
2176 const wxChar
*p
= str
.c_str();
2180 if (n
== dt
.GetDay())
2182 format
.Append(wxT("%d"));
2185 else if (n
== (int)dt
.GetMonth()+1)
2187 format
.Append(wxT("%m"));
2190 else if (n
== dt
.GetYear())
2192 format
.Append(wxT("%Y"));
2195 else if (n
== (dt
.GetYear() % 100))
2198 format
.Append(wxT("%Y"));
2200 format
.Append(wxT("%y"));
2204 format
.Append(*p
++);
2210 bool wxDateProperty::DoSetAttribute( const wxString
& name
, wxVariant
& value
)
2212 if ( name
== wxPG_DATE_FORMAT
)
2214 m_format
= value
.GetString();
2217 else if ( name
== wxPG_DATE_PICKER_STYLE
)
2219 m_dpStyle
= value
.GetLong();
2220 ms_defaultDateFormat
.clear(); // This may need recalculation
2226 #endif // wxUSE_DATETIME
2229 // -----------------------------------------------------------------------
2230 // wxPropertyGridInterface
2231 // -----------------------------------------------------------------------
2233 void wxPropertyGridInterface::InitAllTypeHandlers()
2237 // -----------------------------------------------------------------------
2239 void wxPropertyGridInterface::RegisterAdditionalEditors()
2241 // Register editor classes, if necessary.
2242 if ( wxPGGlobalVars
->m_mapEditorClasses
.empty() )
2243 wxPropertyGrid::RegisterDefaultEditors();
2246 wxPGRegisterEditorClass(SpinCtrl
);
2248 #if wxUSE_DATEPICKCTRL
2249 wxPGRegisterEditorClass(DatePickerCtrl
);
2253 // -----------------------------------------------------------------------
2255 #endif // wxPG_INCLUDE_ADVPROPS
2257 #endif // wxUSE_PROPGRID