1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        advprops.cpp
3 // Purpose:     wxPropertyGrid Advanced Properties (font, colour, etc.)
4 // Author:      Jaakko Salli
5 // Modified by:
6 // Created:     Sep-25-2004
7 // RCS-ID:      $Id:
8 // Copyright:   (c) Jaakko Salli
9 // Licence:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14 
15 #ifdef __BORLANDC__
16     #pragma hdrstop
17 #endif
18 
19 #ifndef WX_PRECOMP
20     #include "wx/defs.h"
21     #include "wx/object.h"
22     #include "wx/hash.h"
23     #include "wx/string.h"
24     #include "wx/log.h"
25     #include "wx/event.h"
26     #include "wx/window.h"
27     #include "wx/panel.h"
28     #include "wx/dc.h"
29     #include "wx/dcclient.h"
30     #include "wx/button.h"
31     #include "wx/pen.h"
32     #include "wx/brush.h"
33     #include "wx/cursor.h"
34     #include "wx/dialog.h"
35     #include "wx/settings.h"
36     #include "wx/msgdlg.h"
37     #include "wx/choice.h"
38     #include "wx/stattext.h"
39     #include "wx/textctrl.h"
40     #include "wx/scrolwin.h"
41     #include "wx/dirdlg.h"
42     #include "wx/combobox.h"
43     #include "wx/layout.h"
44     #include "wx/sizer.h"
45     #include "wx/textdlg.h"
46     #include "wx/filedlg.h"
47     #include "wx/intl.h"
48 #endif
49 
50 #define __wxPG_SOURCE_FILE__
51 
52 #include <wx/propgrid/propgrid.h>
53 
54 #if wxPG_INCLUDE_ADVPROPS
55 
56 #include <wx/propgrid/propdev.h>
57 
58 #include <wx/propgrid/advprops.h>
59 
60 #ifdef __WXMSW__
61     #include <wx/msw/private.h>
62   #if wxCHECK_VERSION(3, 0, 0)
63     #include <wx/msw/dc.h>
64   #endif
65 #endif
66 
67 #if wxPG_USING_WXOWNERDRAWNCOMBOBOX
68     #include <wx/odcombo.h>
69 #else
70     #include <wx/propgrid/odcombo.h>
71 #endif
72 
73 // -----------------------------------------------------------------------
74 
75 #if defined(__WXMSW__)
76     #define wxPG_CAN_DRAW_CURSOR           1
77 #elif defined(__WXGTK__)
78     #define wxPG_CAN_DRAW_CURSOR           0
79 #elif defined(__WXMAC__)
80     #define wxPG_CAN_DRAW_CURSOR           0
81 #else
82     #define wxPG_CAN_DRAW_CURSOR           0
83 #endif
84 
85 
86 // -----------------------------------------------------------------------
87 // Value type related
88 // -----------------------------------------------------------------------
89 
90 
91 // Implement dynamic class for type value.
92 IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue, wxObject)
93 
94 bool operator == (const wxColourPropertyValue& a, const wxColourPropertyValue& b)
95 {
96     return ( ( a.m_colour == b.m_colour ) && (a.m_type == b.m_type) );
97 }
98 
operator ==(const wxArrayInt & array1,const wxArrayInt & array2)99 bool operator == (const wxArrayInt& array1, const wxArrayInt& array2)
100 {
101     if ( array1.GetCount() != array2.GetCount() )
102         return false;
103     size_t i;
104     for ( i=0; i<array1.GetCount(); i++ )
105     {
106         if ( array1[i] != array2[i] )
107             return false;
108     }
109     return true;
110 }
111 
112 // -----------------------------------------------------------------------
113 // wxSpinCtrl-based property editor
114 // -----------------------------------------------------------------------
115 
116 #if wxUSE_SPINBTN
117 
118 #ifdef __WXMSW__
119   #define IS_MOTION_SPIN_SUPPORTED  1
120 #else
121   #define IS_MOTION_SPIN_SUPPORTED  0
122 #endif
123 
124 #if IS_MOTION_SPIN_SUPPORTED
125 //
126 // This class implements ability to rapidly change "spin" value
127 // by moving mouse when one of the spin buttons is depressed.
128 class wxPGSpinButton : public wxSpinButton
129 {
130 public:
wxPGSpinButton()131     wxPGSpinButton() : wxSpinButton()
132     {
133         m_bLeftDown = false;
134         m_hasCapture = false;
135         m_spins = 1;
136 
137         Connect( wxEVT_LEFT_DOWN,
138                  (wxObjectEventFunction) (wxEventFunction)
139                  (wxMouseEventFunction)&wxPGSpinButton::OnMouseEvent );
140         Connect( wxEVT_LEFT_UP,
141                  (wxObjectEventFunction) (wxEventFunction)
142                  (wxMouseEventFunction)&wxPGSpinButton::OnMouseEvent );
143         Connect( wxEVT_MOTION,
144                  (wxObjectEventFunction) (wxEventFunction)
145                  (wxMouseEventFunction)&wxPGSpinButton::OnMouseEvent );
146         Connect( wxEVT_MOUSE_CAPTURE_LOST,
147                  (wxObjectEventFunction) (wxEventFunction)
148                  (wxMouseCaptureLostEventFunction)&wxPGSpinButton::OnMouseCaptureLost );
149     }
150 
151 
GetSpins() const152     int GetSpins() const
153     {
154         return m_spins;
155     }
156 
157 private:
158     wxPoint m_ptPosition;
159 
160     // Having a separate spins variable allows us to handle validation etc. for
161     // multiple spin events at once (with quick mouse movements there could be
162     // hundreds of 'spins' being done at once). Technically things like this
163     // should be stored in event (wxSpinEvent in this case), but there probably
164     // isn't anything there that can be reliably reused.
165     int     m_spins;
166 
167     bool    m_bLeftDown;
168 
169     // SpinButton seems to be a special for mouse capture, so we may need track
170     // privately whether mouse is actually captured.
171     bool    m_hasCapture;
172 
Capture()173     void Capture()
174     {
175         if ( !m_hasCapture )
176         {
177             CaptureMouse();
178             m_hasCapture = true;
179         }
180 
181         SetCursor(wxCURSOR_SIZENS);
182     }
Release()183     void Release()
184     {
185         m_bLeftDown = false;
186 
187         if ( m_hasCapture )
188         {
189             ReleaseMouse();
190             m_hasCapture = false;
191         }
192 
193         wxWindow *parent = GetParent();
194         if ( parent )
195             SetCursor(parent->GetCursor());
196         else
197             SetCursor(wxNullCursor);
198     }
199 
OnMouseEvent(wxMouseEvent & event)200     void OnMouseEvent(wxMouseEvent& event)
201     {
202         if ( event.GetEventType() == wxEVT_LEFT_DOWN )
203         {
204             m_bLeftDown = true;
205             m_ptPosition = event.GetPosition();
206         }
207         else if ( event.GetEventType() == wxEVT_LEFT_UP )
208         {
209             Release();
210             m_bLeftDown = false;
211         }
212         else if ( event.GetEventType() == wxEVT_MOTION )
213         {
214             if ( m_bLeftDown )
215             {
216                 int dy = m_ptPosition.y - event.GetPosition().y;
217                 if ( dy )
218                 {
219                     Capture();
220                     m_ptPosition = event.GetPosition();
221 
222                     wxSpinEvent evtscroll( (dy >= 0) ? wxEVT_SCROLL_LINEUP :
223                                                        wxEVT_SCROLL_LINEDOWN,
224                                            GetId() );
225                     evtscroll.SetEventObject(this);
226 
227                     wxASSERT( m_spins == 1 );
228 
229                     m_spins = abs(dy);
230                     GetEventHandler()->ProcessEvent(evtscroll);
231                     m_spins = 1;
232                 }
233             }
234         }
235 
236         event.Skip();
237     }
OnMouseCaptureLost(wxMouseCaptureLostEvent & WXUNUSED (event))238     void OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
239     {
240         Release();
241     }
242 };
243 
244 #endif // IS_MOTION_SPIN_SUPPORTED
245 
246 
247 // This macro also defines global wxPGEditor_SpinCtrl for storing
248 // the singleton class instance.
WX_PG_IMPLEMENT_EDITOR_CLASS(SpinCtrl,wxPGSpinCtrlEditor,wxPGEditor)249 WX_PG_IMPLEMENT_EDITOR_CLASS(SpinCtrl,wxPGSpinCtrlEditor,wxPGEditor)
250 
251 
252 // Trivial destructor.
253 wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor()
254 {
255     // Reset the global pointer. Useful when wxPropertyGrid is accessed
256     // from an external main loop.
257     wxPG_EDITOR(SpinCtrl) = NULL;
258 }
259 
260 // Create controls and initialize event handling.
CreateControls(wxPropertyGrid * propgrid,wxPGProperty * property,const wxPoint & pos,const wxSize & sz) const261 wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property,
262                                                    const wxPoint& pos, const wxSize& sz ) const
263 {
264     const int margin = 1;
265     wxSize butSz(18, sz.y);
266     wxSize tcSz(sz.x - butSz.x - margin, sz.y);
267     wxPoint butPos(pos.x + tcSz.x + margin, pos.y);
268 
269     wxSpinButton* wnd2;
270 
271 #if IS_MOTION_SPIN_SUPPORTED
272     if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) )
273     {
274         wnd2 = new wxPGSpinButton();
275     }
276     else
277 #endif
278     {
279         wnd2 = new wxSpinButton();
280     }
281 
282 #ifdef __WXMSW__
283     wnd2->Hide();
284 #endif
285     wnd2->Create( propgrid->GetPanel(), wxPG_SUBID2, butPos, butSz, wxSP_VERTICAL );
286 
287     wnd2->SetRange( INT_MIN, INT_MAX );
288     wnd2->SetValue( 0 );
289 
290     propgrid->Connect( wxPG_SUBID1, wxEVT_KEY_DOWN,
291                        (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
292                        &wxPropertyGrid::OnCustomEditorEvent, NULL, propgrid );
293 
294     // Let's add validator to make sure only numbers can be entered
295     wxTextValidator validator(wxFILTER_NUMERIC, &m_tempString);
296 
297     wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz ).m_primary;
298     wnd1->SetValidator(validator);
299 
300     return wxPGWindowList(wnd1, wnd2);
301 }
302 
303 // Control's events are redirected here
OnEvent(wxPropertyGrid * propgrid,wxPGProperty * property,wxWindow * wnd,wxEvent & event) const304 bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
305                                   wxWindow* wnd, wxEvent& event ) const
306 {
307     int evtType = event.GetEventType();
308     int keycode = -1;
309     int spins = 1;
310     bool bigStep = false;
311 
312     if ( evtType == wxEVT_KEY_DOWN )
313     {
314         wxKeyEvent& keyEvent = (wxKeyEvent&)event;
315         keycode = keyEvent.GetKeyCode();
316 
317         if ( keycode == WXK_UP )
318             evtType = wxEVT_SCROLL_LINEUP;
319         else if ( keycode == WXK_DOWN )
320             evtType = wxEVT_SCROLL_LINEDOWN;
321         else if ( keycode == WXK_PAGEUP )
322         {
323             evtType = wxEVT_SCROLL_LINEUP;
324             bigStep = true;
325         }
326         else if ( keycode == WXK_PAGEDOWN )
327         {
328             evtType = wxEVT_SCROLL_LINEDOWN;
329             bigStep = true;
330         }
331     }
332 
333     if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN )
334     {
335     #if IS_MOTION_SPIN_SUPPORTED
336         if ( property->GetAttributeAsLong(wxT("MotionSpin"), 0) )
337         {
338             wxPGSpinButton* spinButton =
339                 (wxPGSpinButton*) propgrid->GetEditorControlSecondary();
340 
341             if ( spinButton )
342                 spins = spinButton->GetSpins();
343         }
344     #endif
345 
346         wxString s;
347         // Can't use wnd since it might be clipper window
348         wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl);
349 
350         if ( tc )
351             s = tc->GetValue();
352         else
353             s = property->GetValueAsString(wxPG_FULL_VALUE);
354 
355         int mode = wxPG_PROPERTY_VALIDATION_SATURATE;
356 
357         if ( property->GetAttributeAsLong(wxT("Wrap"), 0) )
358             mode = wxPG_PROPERTY_VALIDATION_WRAP;
359 
360         if ( property->GetValueType() == wxT("double") )
361         {
362             double v_d;
363             double step = property->GetAttributeAsDouble(wxT("Step"), 1.0);
364 
365             // Try double
366             if ( s.ToDouble(&v_d) )
367             {
368                 if ( bigStep )
369                     step *= 10.0;
370 
371                 step *= (double) spins;
372 
373                 if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step;
374                 else v_d -= step;
375 
376                 // Min/Max check
377                 wxFloatProperty::DoValidation(property, v_d, NULL, mode);
378 
379                 wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL);
380             }
381             else
382             {
383                 return false;
384             }
385         }
386         else
387         {
388             wxLongLong_t v_ll;
389             wxLongLong_t step = property->GetAttributeAsLong(wxT("Step"), 1);
390 
391             // Try long
392             if ( wxPGStringToLongLong(s, &v_ll, 10) )
393             {
394                 if ( bigStep )
395                     step *= 10;
396 
397                 step *= spins;
398 
399                 if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step;
400                 else v_ll -= step;
401 
402                 // Min/Max check
403                 wxIntProperty::DoValidation(property, v_ll, NULL, mode);
404 
405                 s = wxLongLong(v_ll).ToString();
406             }
407             else
408             {
409                 return false;
410             }
411         }
412 
413         if ( tc )
414         {
415             int ip = tc->GetInsertionPoint();
416             int lp = tc->GetLastPosition();
417             tc->SetValue(s);
418             tc->SetInsertionPoint(ip+(tc->GetLastPosition()-lp));
419         }
420 
421         return true;
422     }
423 
424     return wxPGTextCtrlEditor::OnEvent(propgrid,property,wnd,event);
425 }
426 
427 #endif // wxUSE_SPINBTN
428 
429 
430 // -----------------------------------------------------------------------
431 // wxDatePickerCtrl-based property editor
432 // -----------------------------------------------------------------------
433 
434 #if wxUSE_DATEPICKCTRL
435 
436 
437 #include <wx/datectrl.h>
438 #include <wx/dateevt.h>
439 
440 class wxPGDatePickerCtrlEditor : public wxPGEditor
441 {
442     WX_PG_DECLARE_EDITOR_CLASS(wxPGDatePickerCtrlEditor)
443 public:
444     ~wxPGDatePickerCtrlEditor() override;
445 
446     wxPG_DECLARE_CREATECONTROLS
447 
448     void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const override;
449     bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property,
450         wxWindow* wnd, wxEvent& event ) const override;
451     bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* wnd ) const override;
452     void SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const override;
453 };
454 
455 
WX_PG_IMPLEMENT_EDITOR_CLASS(DatePickerCtrl,wxPGDatePickerCtrlEditor,wxPGEditor)456 WX_PG_IMPLEMENT_EDITOR_CLASS(DatePickerCtrl,wxPGDatePickerCtrlEditor,wxPGEditor)
457 
458 
459 wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor()
460 {
461     // Reset the global pointer. Useful when wxPropertyGrid is accessed
462     // from an external main loop.
463     wxPG_EDITOR(DatePickerCtrl) = NULL;
464 }
465 
CreateControls(wxPropertyGrid * propgrid,wxPGProperty * property,const wxPoint & pos,const wxSize & sz) const466 wxPGWindowList wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid,
467                                                          wxPGProperty* property,
468                                                          const wxPoint& pos,
469                                                          const wxSize& sz ) const
470 {
471     wxCHECK_MSG( property->IsKindOf(WX_PG_CLASSINFO(wxDateProperty)),
472                  NULL,
473                  wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") );
474 
475     wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
476 
477     // Use two stage creation to allow cleaner display on wxMSW
478     wxDatePickerCtrl* ctrl = new wxDatePickerCtrl();
479 #ifdef __WXMSW__
480     ctrl->Hide();
481     wxSize useSz = wxDefaultSize;
482     useSz.x = sz.x;
483 #else
484     wxSize useSz = sz;
485 #endif
486 
487     wxDateTime dateValue(wxInvalidDateTime);
488     if ( prop->GetType() == wxT("datetime") )
489         dateValue = prop->GetDateValue();
490 
491     ctrl->Create(propgrid->GetPanel(),
492                  wxPG_SUBID1,
493                  dateValue,
494                  pos,
495                  useSz,
496                  prop->GetDatePickerStyle() |
497                  wxNO_BORDER);
498 
499     // Connect all required events to grid's OnCustomEditorEvent
500     // (all relevenat wxTextCtrl, wxComboBox and wxButton events are
501     // already connected)
502     propgrid->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED,
503                        (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
504                        &wxPropertyGrid::OnCustomEditorEvent );
505 
506 #ifdef __WXMSW__
507     ctrl->Show();
508 #endif
509 
510     return ctrl;
511 }
512 
513 // Copies value from property to control
UpdateControl(wxPGProperty * property,wxWindow * wnd) const514 void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* wnd ) const
515 {
516     wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
517     wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
518 
519     wxDateTime dateValue(wxInvalidDateTime);
520     if ( property->GetType() == wxT("datetime") )
521         dateValue = property->GetValue().GetDateTime();
522 
523     // We assume that property's data type is 'int' (or something similar),
524     // thus allowing us to get raw, unchecked value via DoGetValue.
525     ctrl->SetValue( dateValue );
526 }
527 
528 // Control's events are redirected here
OnEvent(wxPropertyGrid * WXUNUSED (propgrid),wxPGProperty * WXUNUSED (property),wxWindow * WXUNUSED (wnd),wxEvent & event) const529 bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid),
530                                         wxPGProperty* WXUNUSED(property),
531                                         wxWindow* WXUNUSED(wnd),
532                                         wxEvent& event ) const
533 {
534     if ( event.GetEventType() == wxEVT_DATE_CHANGED )
535         return true;
536 
537     return false;
538 }
539 
GetValueFromControl(wxVariant & variant,wxPGProperty * WXUNUSED (property),wxWindow * wnd) const540 bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const
541 {
542     wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
543     wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
544 
545     variant = ctrl->GetValue();
546 
547     return true;
548 }
549 
SetValueToUnspecified(wxPGProperty * property,wxWindow * wnd) const550 void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* property,
551                                                       wxWindow* wnd ) const
552 {
553     wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
554     wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
555 
556     wxDateProperty* prop = wxDynamicCast(property, wxDateProperty);
557 
558     if ( prop )
559     {
560         int datePickerStyle = prop->GetDatePickerStyle();
561         if ( datePickerStyle & wxDP_ALLOWNONE )
562             ctrl->SetValue(wxInvalidDateTime);
563     }
564 }
565 
566 #endif // wxUSE_DATEPICKCTRL
567 
568 
569 // -----------------------------------------------------------------------
570 // wxFontProperty
571 // -----------------------------------------------------------------------
572 
573 #include <wx/fontdlg.h>
574 #include <wx/fontenum.h>
575 
576 static const wxChar* gs_fp_es_family_labels[] = {
577     wxT("Default"), wxT("Decorative"),
578     wxT("Roman"), wxT("Script"),
579     wxT("Swiss"), wxT("Modern"),
580     wxT("Teletype"), wxT("Unknown"),
581     (const wxChar*) NULL
582 };
583 
584 static long gs_fp_es_family_values[] = {
585     wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE,
586     wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT,
587     wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN,
588     wxFONTFAMILY_TELETYPE, wxFONTFAMILY_UNKNOWN
589 };
590 
591 static const wxChar* gs_fp_es_style_labels[] = {
592     wxT("Normal"),
593     wxT("Slant"),
594     wxT("Italic"),
595     (const wxChar*) NULL
596 };
597 
598 static long gs_fp_es_style_values[] = {
599     wxNORMAL,
600     wxSLANT,
601     wxITALIC
602 };
603 
604 static const wxChar* gs_fp_es_weight_labels[] = {
605     wxT("Normal"),
606     wxT("Light"),
607     wxT("Bold"),
608     (const wxChar*) NULL
609 };
610 
611 static long gs_fp_es_weight_values[] = {
612     wxNORMAL,
613     wxLIGHT,
614     wxBOLD
615 };
616 
617 // Class body is in advprops.h
618 
619 
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty,wxFont,const wxFont &,TextCtrlAndButton)620 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty,
621                                wxFont,const wxFont&,TextCtrlAndButton)
622 
623 
624 wxFontProperty::wxFontProperty( const wxString& label, const wxString& name,
625                                 const wxFont& value )
626     : wxPGProperty(label,name)
627 {
628     SetValue( wxFontToVariant(value) );
629 
630     // Initialize font family choices list
631     if ( !wxPGGlobalVars->m_fontFamilyChoices )
632     {
633         wxFontEnumerator enumerator;
634         enumerator.EnumerateFacenames();
635 
636 #if wxMINOR_VERSION > 6
637         wxArrayString faceNames = enumerator.GetFacenames();
638 #else
639         wxArrayString& faceNames = *enumerator.GetFacenames();
640 #endif
641 
642         faceNames.Sort();
643 
644         wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames);
645     }
646 
647     wxString emptyString(wxEmptyString);
648 
649     wxFont& font = wxFontFromVariant(m_value);
650 
651     AddPrivateChild( new wxIntProperty( _("Point Size"), wxT("Point Size"),
652                      (long)font.GetPointSize() ) );
653 
654     AddPrivateChild( new wxEnumProperty(_("Family"), wxT("Family"),
655                      gs_fp_es_family_labels,gs_fp_es_family_values,
656                      font.GetFamily()) );
657 
658     wxString faceName = font.GetFaceName();
659     // If font was not in there, add it now
660     if ( faceName.length() &&
661          wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
662         wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
663 
664     wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxT("Face Name"),
665                                          *wxPGGlobalVars->m_fontFamilyChoices);
666 
667     p->SetValueFromString(faceName, wxPG_FULL_VALUE);
668 
669     AddPrivateChild( p );
670 
671     AddPrivateChild( new wxEnumProperty(_("Style"), wxT("Style"),
672               gs_fp_es_style_labels,gs_fp_es_style_values,font.GetStyle()) );
673 
674     AddPrivateChild( new wxEnumProperty(_("Weight"), wxT("Weight"),
675               gs_fp_es_weight_labels,gs_fp_es_weight_values,font.GetWeight()) );
676 
677     AddPrivateChild( new wxBoolProperty(_("Underlined"), wxT("Underlined"),
678               font.GetUnderlined()) );
679 }
680 
~wxFontProperty()681 wxFontProperty::~wxFontProperty() { }
682 
OnSetValue()683 void wxFontProperty::OnSetValue()
684 {
685     wxFont& font = wxFontFromVariant(m_value);
686     wxASSERT(&font);
687 
688     wxFont font2;
689     if ( !font.Ok() )
690         font2 = *wxNORMAL_FONT;
691     else
692         font2 = font;
693 
694     m_value = wxFontToVariant(font2);
695 }
696 
GetValueAsString(int argFlags) const697 wxString wxFontProperty::GetValueAsString( int argFlags ) const
698 {
699     return wxPGProperty::GetValueAsString(argFlags);
700 }
701 
OnEvent(wxPropertyGrid * propgrid,wxWindow * WXUNUSED (primary),wxEvent & event)702 bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
703                               wxEvent& event )
704 {
705     if ( propgrid->IsMainButtonEvent(event) )
706     {
707         // Update value from last minute changes
708         PrepareValueForDialogEditing(propgrid);
709 
710         wxFontData data;
711         wxFont font;
712 
713         if ( m_value.GetType() == wxT("wxFont") )
714             font = wxFontFromVariant(m_value);
715 
716         data.SetInitialFont( font );
717         data.SetColour(*wxBLACK);
718 
719         wxFontDialog dlg(propgrid, data);
720         if ( dlg.ShowModal() == wxID_OK )
721         {
722             propgrid->EditorsValueWasModified();
723 
724             wxVariant variant = wxFontToVariant(dlg.GetFontData().GetChosenFont());
725             SetValueInEvent( variant );
726             return true;
727         }
728     }
729     return false;
730 }
731 
RefreshChildren()732 void wxFontProperty::RefreshChildren()
733 {
734     if ( !GetCount() ) return;
735     const wxFont& font = wxFontFromVariant(m_value);
736     Item(0)->SetValue( (long)font.GetPointSize() );
737     Item(1)->SetValue( (long)font.GetFamily() );
738     Item(2)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
739     Item(3)->SetValue( (long)font.GetStyle() );
740     Item(4)->SetValue( (long)font.GetWeight() );
741     Item(5)->SetValue( font.GetUnderlined() );
742 }
743 
ChildChanged(wxVariant & thisValue,int ind,wxVariant & childValue) const744 void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const
745 {
746     wxFont& font = wxFontFromVariant(thisValue);
747 
748     if ( ind == 0 )
749     {
750         font.SetPointSize( wxPGVariantToInt(childValue) );
751     }
752     else if ( ind == 1 )
753     {
754         int fam = childValue.GetLong();
755         if ( fam < wxDEFAULT ||
756              fam > wxTELETYPE )
757              fam = wxDEFAULT;
758         font.SetFamily( fam );
759     }
760     else if ( ind == 2 )
761     {
762         wxString faceName;
763         int faceIndex = childValue.GetLong();
764 
765         if ( faceIndex >= 0 )
766             faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
767 
768         font.SetFaceName( faceName );
769     }
770     else if ( ind == 3 )
771     {
772         int st = childValue.GetLong();
773         if ( st != wxFONTSTYLE_NORMAL &&
774              st != wxFONTSTYLE_SLANT &&
775              st != wxFONTSTYLE_ITALIC )
776              st = wxFONTWEIGHT_NORMAL;
777         font.SetStyle( st );
778     }
779     else if ( ind == 4 )
780     {
781         int wt = childValue.GetLong();
782         if ( wt != wxFONTWEIGHT_NORMAL &&
783              wt != wxFONTWEIGHT_LIGHT &&
784              wt != wxFONTWEIGHT_BOLD )
785              wt = wxFONTWEIGHT_NORMAL;
786         font.SetWeight( wt );
787     }
788     else if ( ind == 5 )
789     {
790         font.SetUnderlined( childValue.GetBool() );
791     }
792 }
793 
794 /*
795 wxSize wxFontProperty::OnMeasureImage() const
796 {
797     return wxSize(-1,-1);
798 }
799 
800 void wxFontProperty::OnCustomPaint(wxDC& dc,
801                                         const wxRect& rect,
802                                         wxPGPaintData& paintData)
803 {
804     wxString drawFace;
805     if ( paintData.m_choiceItem >= 0 )
806         drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
807     else
808         drawFace = m_value_wxFont.GetFaceName();
809 
810     if ( drawFace.length() )
811     {
812         // Draw the background
813         dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
814         //dc.SetBrush( *wxWHITE_BRUSH );
815         //dc.SetPen( *wxMEDIUM_GREY_PEN );
816         dc.DrawRectangle( rect );
817 
818         wxFont oldFont = dc.GetFont();
819         wxFont drawFont(oldFont.GetPointSize(),
820                         wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
821         dc.SetFont(drawFont);
822 
823         dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
824         dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
825 
826         dc.SetFont(oldFont);
827     }
828     else
829     {
830         // No file - just draw a white box
831         dc.SetBrush ( *wxWHITE_BRUSH );
832         dc.DrawRectangle ( rect );
833     }
834 }
835 */
836 
837 
838 // -----------------------------------------------------------------------
839 // wxSystemColourProperty
840 // -----------------------------------------------------------------------
841 
842 // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
843 #define wxPG_PROP_HIDE_CUSTOM_COLOUR        wxPG_PROP_CLASS_SPECIFIC_2
844 
845 #include <wx/colordlg.h>
846 
847 //#define wx_cp_es_syscolours_len 25
848 static const wxChar* gs_cp_es_syscolour_labels[] = {
849     wxT("AppWorkspace"),
850     wxT("ActiveBorder"),
851     wxT("ActiveCaption"),
852     wxT("ButtonFace"),
853     wxT("ButtonHighlight"),
854     wxT("ButtonShadow"),
855     wxT("ButtonText"),
856     wxT("CaptionText"),
857     wxT("ControlDark"),
858     wxT("ControlLight"),
859     wxT("Desktop"),
860     wxT("GrayText"),
861     wxT("Highlight"),
862     wxT("HighlightText"),
863     wxT("InactiveBorder"),
864     wxT("InactiveCaption"),
865     wxT("InactiveCaptionText"),
866     wxT("Menu"),
867     wxT("Scrollbar"),
868     wxT("Tooltip"),
869     wxT("TooltipText"),
870     wxT("Window"),
871     wxT("WindowFrame"),
872     wxT("WindowText"),
873     wxT("Custom"),
874     (const wxChar*) NULL
875 };
876 
877 static long gs_cp_es_syscolour_values[] = {
878     wxSYS_COLOUR_APPWORKSPACE,
879     wxSYS_COLOUR_ACTIVEBORDER,
880     wxSYS_COLOUR_ACTIVECAPTION,
881     wxSYS_COLOUR_BTNFACE,
882     wxSYS_COLOUR_BTNHIGHLIGHT,
883     wxSYS_COLOUR_BTNSHADOW,
884     wxSYS_COLOUR_BTNTEXT ,
885     wxSYS_COLOUR_CAPTIONTEXT,
886     wxSYS_COLOUR_3DDKSHADOW,
887     wxSYS_COLOUR_3DLIGHT,
888     wxSYS_COLOUR_BACKGROUND,
889     wxSYS_COLOUR_GRAYTEXT,
890     wxSYS_COLOUR_HIGHLIGHT,
891     wxSYS_COLOUR_HIGHLIGHTTEXT,
892     wxSYS_COLOUR_INACTIVEBORDER,
893     wxSYS_COLOUR_INACTIVECAPTION,
894     wxSYS_COLOUR_INACTIVECAPTIONTEXT,
895     wxSYS_COLOUR_MENU,
896     wxSYS_COLOUR_SCROLLBAR,
897     wxSYS_COLOUR_INFOBK,
898     wxSYS_COLOUR_INFOTEXT,
899     wxSYS_COLOUR_WINDOW,
900     wxSYS_COLOUR_WINDOWFRAME,
901     wxSYS_COLOUR_WINDOWTEXT,
902     wxPG_COLOUR_CUSTOM
903 };
904 
905 
WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA_WITH_PROPER_EQ(wxPGVariantDataColourPropertyValue,wxColourPropertyValue)906 WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA_WITH_PROPER_EQ(wxPGVariantDataColourPropertyValue,
907                                                      wxColourPropertyValue)
908 
909 
910 // Class body is in advprops.h
911 
912 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
913                                wxColourPropertyValue,const wxColourPropertyValue&,Choice)
914 
915 
916 void wxSystemColourProperty::Init( int type, const wxColour& colour )
917 {
918     wxColourPropertyValue cpv;
919 
920     if ( colour.Ok() )
921         cpv.Init( type, colour );
922     else
923         cpv.Init( type, *wxWHITE );
924 
925     m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
926 
927     m_value = wxColourPropertyValueToVariant(cpv);
928 
929     OnSetValue();
930 }
931 
932 
933 static wxPGChoices gs_wxSystemColourProperty_choicesCache;
934 
935 
wxSystemColourProperty(const wxString & label,const wxString & name,const wxColourPropertyValue & value)936 wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
937     const wxColourPropertyValue& value )
938     : wxEnumProperty( label,
939                       name,
940                       gs_cp_es_syscolour_labels,
941                       gs_cp_es_syscolour_values,
942                       &gs_wxSystemColourProperty_choicesCache )
943 {
944     Init( value.m_type, value.m_colour );
945 }
946 
947 
wxSystemColourProperty(const wxString & label,const wxString & name,const wxChar ** labels,const long * values,wxPGChoices * choicesCache,const wxColourPropertyValue & value)948 wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
949     const wxChar** labels, const long* values, wxPGChoices* choicesCache,
950     const wxColourPropertyValue& value )
951     : wxEnumProperty( label, name, labels, values, choicesCache )
952 {
953     Init( value.m_type, value.m_colour );
954 }
955 
956 
wxSystemColourProperty(const wxString & label,const wxString & name,const wxChar ** labels,const long * values,wxPGChoices * choicesCache,const wxColour & value)957 wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
958     const wxChar** labels, const long* values, wxPGChoices* choicesCache,
959     const wxColour& value )
960     : wxEnumProperty( label, name, labels, values, choicesCache )
961 {
962     Init( wxPG_COLOUR_CUSTOM, value );
963 }
964 
965 
~wxSystemColourProperty()966 wxSystemColourProperty::~wxSystemColourProperty() { }
967 
968 
GetVal(const wxVariant * pVariant) const969 wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
970 {
971     if ( !pVariant )
972         pVariant = &m_value;
973 
974     if ( pVariant->IsNull() )
975         return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
976 
977     wxColourPropertyValue* v1 = &wxColourPropertyValueFromVariant(*pVariant);
978     if ( v1 )
979         return *v1;
980 
981     wxColour* pCol = wxGetVariantCast(*pVariant, wxColour);
982     wxColour col;
983 
984     if ( pCol )
985         col = *pCol;
986     else
987         col << *pVariant;
988 
989     wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
990 
991     int colInd = ColToInd(col);
992     if ( colInd != wxNOT_FOUND )
993         v2.m_type = colInd;
994 
995     return v2;
996 }
997 
DoTranslateVal(wxColourPropertyValue & v) const998 wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
999 {
1000     return wxColourPropertyValueToVariant(v);
1001 }
1002 
ColToInd(const wxColour & colour) const1003 int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
1004 {
1005     size_t i;
1006     size_t i_max = m_choices.GetCount();
1007 
1008     if ( !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1009         i_max -= 1;
1010 
1011     for ( i=0; i<i_max; i++ )
1012     {
1013         int ind = m_choices[i].GetValue();
1014 
1015         if ( colour == GetColour(ind) )
1016         {
1017             /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1018                 GetClassName(),GetLabel().c_str(),
1019                 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1020                 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1021             return ind;
1022         }
1023     }
1024     return wxNOT_FOUND;
1025 }
1026 
1027 
wxColourFromPGLong(long col)1028 static inline wxColour wxColourFromPGLong( long col )
1029 {
1030     return wxColour((col&0xFF),((col>>8)&0xFF),((col>>16)&0xFF));
1031 }
1032 
1033 
OnSetValue()1034 void wxSystemColourProperty::OnSetValue()
1035 {
1036     // Convert from generic wxobject ptr to wxPGVariantDataColour
1037     if ( wxPGIsVariantType(m_value, wxobject) )
1038     {
1039         wxASSERT( m_value.IsValueKindOf(CLASSINFO(wxColour)) );
1040         wxColour* pCol = (wxColour*) m_value.GetWxObjectPtr();
1041         m_value << *pCol;
1042     }
1043 
1044     wxColourPropertyValue val = GetVal(&m_value);
1045 
1046     if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
1047     {
1048         m_value.MakeNull();
1049         return;
1050     }
1051     else
1052     {
1053 
1054         if ( val.m_type < wxPG_COLOUR_WEB_BASE )
1055             val.m_colour = GetColour( val.m_type );
1056 
1057         m_value = TranslateVal(val);
1058     }
1059 
1060     wxColourPropertyValue* pCpv = &wxColourPropertyValueFromVariant(m_value);
1061     wxColour col;
1062     if ( pCpv )
1063         col = pCpv->m_colour;
1064     else
1065         col << m_value;
1066 
1067     if ( !col.Ok() )
1068     {
1069         SetValueToUnspecified();
1070         SetIndex(wxNOT_FOUND);
1071         return;
1072     }
1073 
1074     int ind;
1075 
1076     if ( pCpv )
1077     {
1078         if ( pCpv->m_type < wxPG_COLOUR_WEB_BASE ||
1079              (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1080         {
1081             ind = GetIndexForValue(pCpv->m_type);
1082         }
1083         else
1084         {
1085             pCpv->m_type = wxPG_COLOUR_CUSTOM;
1086             ind = GetCustomColourIndex();
1087         }
1088     }
1089     else
1090     {
1091         ind = ColToInd(col);
1092 
1093         if ( ind == wxNOT_FOUND &&
1094              !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1095             ind = GetCustomColourIndex();
1096     }
1097 
1098     SetIndex(ind);
1099 }
1100 
1101 
GetColour(int index) const1102 wxColour wxSystemColourProperty::GetColour( int index ) const
1103 {
1104     return wxSystemSettings::GetColour( (wxSystemColour)index );
1105 }
1106 
ColourToString(const wxColour & col,int index) const1107 wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
1108 {
1109     if ( index == wxNOT_FOUND )
1110         return wxString::Format(wxT("(%i,%i,%i)"),
1111                                 (int)col.Red(),
1112                                 (int)col.Green(),
1113                                 (int)col.Blue());
1114     else
1115         return m_choices.GetLabel(index);
1116 }
1117 
GetValueAsString(int argFlags) const1118 wxString wxSystemColourProperty::GetValueAsString( int argFlags ) const
1119 {
1120     wxColourPropertyValue val = GetVal();
1121 
1122     int ind = GetIndex();
1123 
1124     // Always show custom colour for textctrl-editor
1125     if ( (val.m_type == wxPG_COLOUR_CUSTOM ||
1126           (ind == GetCustomColourIndex() &&
1127             !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR)) ||
1128           (argFlags & wxPG_PROPERTY_SPECIFIC)) )
1129     {
1130         return ColourToString(val.m_colour, wxNOT_FOUND);
1131     }
1132 
1133     if ( ind == -1 )
1134         return wxEmptyString;
1135 
1136     return ColourToString(val.m_colour, ind);
1137 }
1138 
1139 
OnMeasureImage(int) const1140 wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1141 {
1142     return wxPG_DEFAULT_IMAGE_SIZE;
1143 }
1144 
1145 
GetCustomColourIndex() const1146 int wxSystemColourProperty::GetCustomColourIndex() const
1147 {
1148     return m_choices.GetCount() - 1;
1149 }
1150 
1151 
QueryColourFromUser(wxVariant & variant) const1152 bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1153 {
1154     wxASSERT( m_value.GetType() != wxT("string") );
1155     bool res = false;
1156 
1157     wxPropertyGrid* propgrid = GetGrid();
1158     wxASSERT( propgrid );
1159 
1160     // Must only occur when user triggers event
1161     if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT) )
1162         return res;
1163 
1164     wxColourPropertyValue val = GetVal();
1165 
1166     val.m_type = wxPG_COLOUR_CUSTOM;
1167 
1168     wxColourData data;
1169     data.SetChooseFull(true);
1170     data.SetColour(val.m_colour);
1171     int i;
1172     for ( i = 0; i < 16; i++)
1173     {
1174         wxColour colour(i*16, i*16, i*16);
1175         data.SetCustomColour(i, colour);
1176     }
1177 
1178     wxColourDialog dialog(propgrid, &data);
1179     if ( dialog.ShowModal() == wxID_OK )
1180     {
1181         wxColourData retData = dialog.GetColourData();
1182         val.m_colour = retData.GetColour();
1183 
1184         variant = DoTranslateVal(val);
1185 
1186         SetValueInEvent(variant);
1187 
1188         res = true;
1189     }
1190 
1191     return res;
1192 }
1193 
1194 
IntToValue(wxVariant & variant,int number,int WXUNUSED (argFlags)) const1195 bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1196 {
1197     int index = number;
1198     int type = GetValueForIndex(index);
1199 
1200     if ( type == wxPG_COLOUR_CUSTOM )
1201     {
1202         QueryColourFromUser(variant);
1203     }
1204     else
1205     {
1206         variant = TranslateVal( type, GetColour(type) );
1207     }
1208 
1209     return true;
1210 }
1211 
1212 // Need to do some extra event handling.
OnEvent(wxPropertyGrid * propgrid,wxWindow * WXUNUSED (primary),wxEvent & event)1213 bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid,
1214                                       wxWindow* WXUNUSED(primary),
1215                                       wxEvent& event )
1216 {
1217     bool askColour = false;
1218 
1219     if ( propgrid->IsMainButtonEvent(event) )
1220     {
1221         askColour = true;
1222     }
1223     else if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
1224     {
1225 		// Must override index detection since at this point GetIndex()
1226 		// will return old value.
1227 		wxPGOwnerDrawnComboBox* cb =
1228 			(wxPGOwnerDrawnComboBox*)propgrid->GetEditorControl();
1229 
1230 		if ( cb )
1231 		{
1232 			int index = cb->GetSelection();
1233 
1234 			if ( index == GetCustomColourIndex() &&
1235 				 !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1236 				askColour = true;
1237 		}
1238     }
1239 
1240     if ( askColour && !propgrid->WasValueChangedInEvent() )
1241     {
1242         // We need to handle button click in case editor has been
1243         // switched to one that has wxButton as well.
1244         wxVariant variant;
1245         if ( QueryColourFromUser(variant) )
1246             return true;
1247     }
1248     return false;
1249 }
1250 
1251 /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1252 {
1253 public:
1254     virtual void Render( wxDC& dc, const wxRect& rect,
1255                          const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1256                          int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1257     {
1258         wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1259         wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1260 
1261         dc.SetPen(*wxBLACK_PEN);
1262         if ( item >= 0 &&
1263              ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1264            )
1265         {
1266             int colInd;
1267             const wxArrayInt& values = prop->GetValues();
1268             if ( values.GetCount() )
1269                 colInd = values[item];
1270             else
1271                 colInd = item;
1272             dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1273         }
1274         else if ( !prop->IsValueUnspecified() )
1275             dc.SetBrush( prop->GetVal().m_colour );
1276         else
1277             dc.SetBrush( *wxWHITE );
1278 
1279         wxRect imageRect = propertyGrid->GetImageRect(property, item);
1280         wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1281         dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1282                           imageRect.width, imageRect.height );
1283 
1284         wxString text;
1285         if ( item == -1 )
1286             text = property->GetValueAsString();
1287         else
1288             text = property->GetChoiceString(item);
1289         DrawText( dc, rect, imageRect.width, text );
1290     }
1291 protected:
1292 };
1293 
1294 wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1295 
1296 wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1297 {
1298     if ( column == 1 )
1299         return &g_wxPGColourPropertyRenderer;
1300     return wxEnumProperty::GetCellRenderer(column);
1301 }*/
1302 
OnCustomPaint(wxDC & dc,const wxRect & rect,wxPGPaintData & paintdata)1303 void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1304                                             wxPGPaintData& paintdata )
1305 {
1306     wxColour col;
1307 
1308     if ( paintdata.m_choiceItem >= 0 &&
1309          paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1310          (paintdata.m_choiceItem != GetCustomColourIndex() ||
1311           m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1312     {
1313         int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1314         col = GetColour( colInd );
1315     }
1316     else if ( !IsValueUnspecified() )
1317     {
1318         col = GetVal().m_colour;
1319     }
1320 
1321     if ( col.Ok() )
1322     {
1323         dc.SetBrush(col);
1324         dc.DrawRectangle(rect);
1325     }
1326 }
1327 
1328 
StringToValue(wxVariant & value,const wxString & text,int argFlags) const1329 bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1330 {
1331     //
1332     // Accept colour format "[Name] [(R,G,B)]"
1333     // Name takes precedence.
1334     //
1335     wxString colourName;
1336     wxString colourRGB;
1337 
1338     int ppos = text.Find(wxT("("));
1339 
1340     if ( ppos == wxNOT_FOUND )
1341     {
1342         colourName = text;
1343     }
1344     else
1345     {
1346         colourName = text.substr(0, ppos);
1347         colourRGB = text.substr(ppos, text.length()-ppos);
1348     }
1349 
1350     // Strip spaces from extremities
1351     colourName.Trim(true);
1352     colourName.Trim(false);
1353     colourRGB.Trim(true);
1354 
1355     // Validate colourRGB string - (1,1,1) is shortest allowed
1356     if ( colourRGB.length() < 7 )
1357         colourRGB.clear();
1358 
1359     if ( colourRGB.length() == 0 && m_choices.GetCount() &&
1360          !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) &&
1361          colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1362     {
1363         if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1364         {
1365             // This really should not occurr...
1366             // wxASSERT(false);
1367             ResetNextIndex();
1368             return false;
1369         }
1370 
1371         QueryColourFromUser(value);
1372     }
1373     else
1374     {
1375         wxColourPropertyValue val;
1376 
1377         bool done = false;
1378 
1379         if ( colourName.length() )
1380         {
1381             // Try predefined colour first
1382             bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1383             if ( res && GetIndex() >= 0 )
1384             {
1385                 val.m_type = GetIndex();
1386                 if ( val.m_type >= 0 && val.m_type < m_choices.GetCount() )
1387                     val.m_type = m_choices[val.m_type].GetValue();
1388 
1389                 // Get proper colour for type.
1390                 val.m_colour = GetColour(val.m_type);
1391 
1392                 done = true;
1393             }
1394         }
1395         if ( colourRGB.length() && !done )
1396         {
1397             // Then check custom colour.
1398             val.m_type = wxPG_COLOUR_CUSTOM;
1399 
1400             int r = -1, g = -1, b = -1;
1401             wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1402 
1403             if ( r >= 0 && r <= 255 &&
1404                  g >= 0 && g <= 255 &&
1405                  b >= 0 && b <= 255 )
1406             {
1407                 val.m_colour.Set(r,g,b);
1408 
1409                 done = true;
1410             }
1411         }
1412 
1413         if ( !done )
1414         {
1415             ResetNextIndex();
1416             return false;
1417         }
1418 
1419         value = DoTranslateVal(val);
1420     }
1421 
1422     return true;
1423 }
1424 
1425 
DoSetAttribute(const wxString & name,wxVariant & value)1426 bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1427 {
1428     if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1429     {
1430         int ival = wxPGVariantToInt(value);
1431 
1432         SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
1433 
1434         if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1435         {
1436             // Show custom choice
1437             m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1438             m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1439         }
1440         else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1441         {
1442             // Hide custom choice
1443             m_choices.RemoveAt(GetCustomColourIndex());
1444             m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1445         }
1446         return true;
1447     }
1448     return false;
1449 }
1450 
1451 
1452 // -----------------------------------------------------------------------
1453 // wxColourProperty
1454 // -----------------------------------------------------------------------
1455 
1456 static const wxChar* gs_cp_es_normcolour_labels[] = {
1457     wxT("Black"),
1458     wxT("Maroon"),
1459     wxT("Navy"),
1460     wxT("Purple"),
1461     wxT("Teal"),
1462     wxT("Gray"),
1463     wxT("Green"),
1464     wxT("Olive"),
1465     wxT("Brown"),
1466     wxT("Blue"),
1467     wxT("Fuchsia"),
1468     wxT("Red"),
1469     wxT("Orange"),
1470     wxT("Silver"),
1471     wxT("Lime"),
1472     wxT("Aqua"),
1473     wxT("Yellow"),
1474     wxT("White"),
1475     wxT("Custom"),
1476     (const wxChar*) NULL
1477 };
1478 
1479 static unsigned long gs_cp_es_normcolour_colours[] = {
1480     wxPG_COLOUR(0,0,0),
1481     wxPG_COLOUR(128,0,0),
1482     wxPG_COLOUR(0,0,128),
1483     wxPG_COLOUR(128,0,128),
1484     wxPG_COLOUR(0,128,128),
1485     wxPG_COLOUR(128,128,128),
1486     wxPG_COLOUR(0,128,0),
1487     wxPG_COLOUR(128,128,0),
1488     wxPG_COLOUR(166,124,81),
1489     wxPG_COLOUR(0,0,255),
1490     wxPG_COLOUR(255,0,255),
1491     wxPG_COLOUR(255,0,0),
1492     wxPG_COLOUR(247,148,28),
1493     wxPG_COLOUR(192,192,192),
1494     wxPG_COLOUR(0,255,0),
1495     wxPG_COLOUR(0,255,255),
1496     wxPG_COLOUR(255,255,0),
1497     wxPG_COLOUR(255,255,255),
1498     wxPG_COLOUR(0,0,0)
1499 };
1500 
1501 WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR2(wxColourProperty,
1502                                                      gs_cp_es_normcolour_labels,
1503                                                      (const long*)NULL,
1504                                                      gs_cp_es_normcolour_colours,
1505                                                      TextCtrlAndButton)
1506 
1507 // -----------------------------------------------------------------------
1508 // wxCursorProperty
1509 // -----------------------------------------------------------------------
1510 
1511 #define wxPG_CURSOR_IMAGE_WIDTH     32
1512 
1513 #define NUM_CURSORS 28
1514 
1515 //#define wx_cp_es_syscursors_len 28
1516 static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1517     wxT("Default"),
1518     wxT("Arrow"),
1519     wxT("Right Arrow"),
1520     wxT("Blank"),
1521     wxT("Bullseye"),
1522     wxT("Character"),
1523     wxT("Cross"),
1524     wxT("Hand"),
1525     wxT("I-Beam"),
1526     wxT("Left Button"),
1527     wxT("Magnifier"),
1528     wxT("Middle Button"),
1529     wxT("No Entry"),
1530     wxT("Paint Brush"),
1531     wxT("Pencil"),
1532     wxT("Point Left"),
1533     wxT("Point Right"),
1534     wxT("Question Arrow"),
1535     wxT("Right Button"),
1536     wxT("Sizing NE-SW"),
1537     wxT("Sizing N-S"),
1538     wxT("Sizing NW-SE"),
1539     wxT("Sizing W-E"),
1540     wxT("Sizing"),
1541     wxT("Spraycan"),
1542     wxT("Wait"),
1543     wxT("Watch"),
1544     wxT("Wait Arrow"),
1545     (const wxChar*) NULL
1546 };
1547 
1548 static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1549     wxCURSOR_NONE,
1550     wxCURSOR_ARROW,
1551     wxCURSOR_RIGHT_ARROW,
1552     wxCURSOR_BLANK,
1553     wxCURSOR_BULLSEYE,
1554     wxCURSOR_CHAR,
1555     wxCURSOR_CROSS,
1556     wxCURSOR_HAND,
1557     wxCURSOR_IBEAM,
1558     wxCURSOR_LEFT_BUTTON,
1559     wxCURSOR_MAGNIFIER,
1560     wxCURSOR_MIDDLE_BUTTON,
1561     wxCURSOR_NO_ENTRY,
1562     wxCURSOR_PAINT_BRUSH,
1563     wxCURSOR_PENCIL,
1564     wxCURSOR_POINT_LEFT,
1565     wxCURSOR_POINT_RIGHT,
1566     wxCURSOR_QUESTION_ARROW,
1567     wxCURSOR_RIGHT_BUTTON,
1568     wxCURSOR_SIZENESW,
1569     wxCURSOR_SIZENS,
1570     wxCURSOR_SIZENWSE,
1571     wxCURSOR_SIZEWE,
1572     wxCURSOR_SIZING,
1573     wxCURSOR_SPRAYCAN,
1574     wxCURSOR_WAIT,
1575     wxCURSOR_WATCH,
1576     wxCURSOR_ARROWWAIT
1577 };
1578 
IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty,wxEnumProperty)1579 IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1580 
1581 wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1582     int value )
1583     : wxEnumProperty( label,
1584                       name,
1585                       gs_cp_es_syscursors_labels,
1586                       gs_cp_es_syscursors_values,
1587                       value )
1588 {
1589     m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1590 }
1591 
~wxCursorProperty()1592 wxCursorProperty::~wxCursorProperty()
1593 {
1594 }
1595 
OnMeasureImage(int item) const1596 wxSize wxCursorProperty::OnMeasureImage( int item ) const
1597 {
1598 #if wxPG_CAN_DRAW_CURSOR
1599     if ( item != -1 && item < NUM_CURSORS )
1600         return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1601 #endif
1602     return wxSize(0,0);
1603 }
1604 
1605 #if wxPG_CAN_DRAW_CURSOR
1606 
OnCustomPaint(wxDC & dc,const wxRect & rect,wxPGPaintData & paintdata)1607 void wxCursorProperty::OnCustomPaint( wxDC& dc,
1608                                       const wxRect& rect,
1609                                       wxPGPaintData& paintdata )
1610 {
1611     // Background brush
1612     dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1613 
1614     if ( paintdata.m_choiceItem >= 0 )
1615     {
1616         dc.DrawRectangle( rect );
1617 
1618         if ( paintdata.m_choiceItem < NUM_CURSORS )
1619         {
1620             int cursorindex = gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1621 
1622             {
1623                 if ( cursorindex == wxCURSOR_NONE )
1624                     cursorindex = wxCURSOR_ARROW;
1625 
1626                 wxCursor cursor( cursorindex );
1627 
1628             #ifdef __WXMSW__
1629                   ::DrawIconEx( wxPG_GetHDCOf(dc),
1630                               rect.x,
1631                               rect.y,
1632                               (HICON)cursor.GetHandle(),
1633                               0,
1634                               0,
1635                               0,
1636                               NULL,
1637             #if !defined(__WXWINCE__)
1638                               DI_COMPAT | DI_DEFAULTSIZE |
1639             #endif
1640                               DI_NORMAL
1641                             );
1642             #endif
1643             }
1644         }
1645     }
1646 }
1647 
1648 #else
OnCustomPaint(wxDC &,const wxRect &,wxPGPaintData &)1649 void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1650 /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1651 {
1652     return wxEnumProperty::GetCellRenderer(column);
1653 }*/
1654 #endif
1655 
1656 // -----------------------------------------------------------------------
1657 // wxImageFileProperty
1658 // -----------------------------------------------------------------------
1659 
1660 #if wxUSE_IMAGE
1661 
wxPGGetDefaultImageWildcard()1662 const wxString& wxPGGetDefaultImageWildcard()
1663 {
1664     // Form the wildcard, if not done yet
1665     if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1666     {
1667 
1668         wxString str;
1669 
1670         // TODO: This section may require locking (using global).
1671 
1672         wxList& handlers = wxImage::GetHandlers();
1673 
1674         wxList::iterator node;
1675 
1676         // Let's iterate over the image handler list.
1677         //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1678         for ( node = handlers.begin(); node != handlers.end(); node++ )
1679         {
1680             wxImageHandler *handler = (wxImageHandler*)*node;
1681 
1682             wxString ext_lo = handler->GetExtension();
1683             wxString ext_up = ext_lo.Upper();
1684 
1685             str.append( ext_up );
1686             str.append( wxT(" files (*.") );
1687             str.append( ext_up );
1688             str.append( wxT(")|*.") );
1689             str.append( ext_lo );
1690             str.append( wxT("|") );
1691         }
1692 
1693         str.append ( wxT("All files (*.*)|*.*") );
1694 
1695         wxPGGlobalVars->m_pDefaultImageWildcard = str;
1696     }
1697 
1698     return wxPGGlobalVars->m_pDefaultImageWildcard;
1699 }
1700 
WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxImageFileProperty,wxFileProperty,const wxString &)1701 WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxImageFileProperty,
1702                                        wxFileProperty,
1703                                        const wxString&)
1704 
1705 wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1706     const wxString& value )
1707     : wxFileProperty(label,name,value)
1708 {
1709     SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1710 
1711     m_pImage = (wxImage*) NULL;
1712     m_pBitmap = (wxBitmap*) NULL;
1713 }
1714 
~wxImageFileProperty()1715 wxImageFileProperty::~wxImageFileProperty()
1716 {
1717     if ( m_pBitmap )
1718         delete m_pBitmap;
1719     if ( m_pImage )
1720         delete m_pImage;
1721 }
1722 
OnSetValue()1723 void wxImageFileProperty::OnSetValue()
1724 {
1725     wxFileProperty::OnSetValue();
1726 
1727     // Delete old image
1728     if ( m_pImage )
1729     {
1730         delete m_pImage;
1731         m_pImage = NULL;
1732     }
1733     if ( m_pBitmap )
1734     {
1735         delete m_pBitmap;
1736         m_pBitmap = NULL;
1737     }
1738 
1739     // Create the image thumbnail
1740     if ( m_filename.FileExists() )
1741     {
1742         m_pImage = new wxImage( m_filename.GetFullPath() );
1743     }
1744 }
1745 
OnMeasureImage(int) const1746 wxSize wxImageFileProperty::OnMeasureImage( int ) const
1747 {
1748     return wxPG_DEFAULT_IMAGE_SIZE;
1749 }
1750 
OnCustomPaint(wxDC & dc,const wxRect & rect,wxPGPaintData &)1751 void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1752                                          const wxRect& rect,
1753                                          wxPGPaintData& )
1754 {
1755     if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1756     {
1757         // Draw the thumbnail
1758 
1759         // Create the bitmap here because required size is not known in OnSetValue().
1760         if ( !m_pBitmap )
1761         {
1762             m_pImage->Rescale( rect.width, rect.height );
1763             m_pBitmap = new wxBitmap( *m_pImage );
1764             delete m_pImage;
1765             m_pImage = NULL;
1766         }
1767 
1768         dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1769     }
1770     else
1771     {
1772         // No file - just draw a white box
1773         dc.SetBrush( *wxWHITE_BRUSH );
1774         dc.DrawRectangle ( rect );
1775     }
1776 }
1777 
1778 #endif // wxUSE_IMAGE
1779 
1780 // -----------------------------------------------------------------------
1781 // wxMultiChoiceProperty
1782 // -----------------------------------------------------------------------
1783 
1784 #if wxUSE_CHOICEDLG
1785 
1786 #include <wx/choicdlg.h>
1787 
WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,wxArrayInt,const wxArrayInt &,TextCtrlAndButton)1788 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1789                                wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1790 
1791 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1792                                               const wxString& name,
1793                                               const wxPGChoices& choices,
1794                                               const wxArrayString& value)
1795                                                 : wxPGProperty(label,name)
1796 {
1797     m_choices.Assign(choices);
1798     SetValue(value);
1799 }
1800 
wxMultiChoiceProperty(const wxString & label,const wxString & name,const wxArrayString & strings,const wxArrayString & value)1801 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1802                                               const wxString& name,
1803                                               const wxArrayString& strings,
1804                                               const wxArrayString& value)
1805                                                 : wxPGProperty(label,name)
1806 {
1807     m_choices.Set(strings);
1808     SetValue(value);
1809 }
1810 
wxMultiChoiceProperty(const wxString & label,const wxString & name,const wxArrayString & value)1811 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1812                                               const wxString& name,
1813                                               const wxArrayString& value)
1814                                                 : wxPGProperty(label,name)
1815 {
1816     wxArrayString strings;
1817     m_choices.Set(strings);
1818     SetValue(value);
1819 }
1820 
~wxMultiChoiceProperty()1821 wxMultiChoiceProperty::~wxMultiChoiceProperty()
1822 {
1823 }
1824 
OnSetValue()1825 void wxMultiChoiceProperty::OnSetValue()
1826 {
1827     GenerateValueAsString();
1828 }
1829 
GetValueAsString(int) const1830 wxString wxMultiChoiceProperty::GetValueAsString( int ) const
1831 {
1832     return m_display;
1833 }
1834 
GenerateValueAsString()1835 void wxMultiChoiceProperty::GenerateValueAsString()
1836 {
1837     wxArrayString strings;
1838 
1839     if ( wxPGIsVariantType(m_value, arrstring) )
1840         strings = m_value.GetArrayString();
1841 
1842     wxString& tempStr = m_display;
1843     unsigned int i;
1844     unsigned int itemCount = strings.GetCount();
1845 
1846     tempStr.Empty();
1847 
1848     if ( itemCount )
1849         tempStr.append( wxT("\"") );
1850 
1851     for ( i = 0; i < itemCount; i++ )
1852     {
1853         tempStr.append( strings[i] );
1854         tempStr.append( wxT("\"") );
1855         if ( i < (itemCount-1) )
1856             tempStr.append ( wxT(" \"") );
1857     }
1858 }
1859 
GetValueAsIndices() const1860 wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1861 {
1862     const wxArrayInt& valueArr = wxArrayIntFromVariant(GetValue());
1863     unsigned int i;
1864 
1865     // Translate values to string indices.
1866     wxArrayInt selections;
1867 
1868     if ( !m_choices.IsOk() || !m_choices.GetCount() )
1869     {
1870         for ( i=0; i<valueArr.GetCount(); i++ )
1871             selections.Add(-1);
1872     }
1873     else
1874     {
1875         for ( i=0; i<valueArr.GetCount(); i++ )
1876         {
1877             int sIndex = m_choices.Index(valueArr[i]);
1878             if ( sIndex >= 0 )
1879                 selections.Add(sIndex);
1880         }
1881     }
1882 
1883     return selections;
1884 }
1885 
OnEvent(wxPropertyGrid * propgrid,wxWindow * WXUNUSED (primary),wxEvent & event)1886 bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1887                                      wxWindow* WXUNUSED(primary),
1888                                      wxEvent& event )
1889 {
1890     if ( propgrid->IsMainButtonEvent(event) )
1891     {
1892         // Update the value
1893         PrepareValueForDialogEditing(propgrid);
1894 
1895         wxArrayString labels = m_choices.GetLabels();
1896         unsigned int choiceCount;
1897 
1898         if ( m_choices.IsOk() )
1899             choiceCount = m_choices.GetCount();
1900         else
1901             choiceCount = 0;
1902 
1903         // launch editor dialog
1904         wxMultiChoiceDialog dlg( propgrid,
1905                                  _("Make a selection:"),
1906                                  m_label,
1907                                  choiceCount,
1908                                  choiceCount?&labels[0]:NULL,
1909                                  wxCHOICEDLG_STYLE );
1910 
1911         dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
1912 
1913         wxArrayString strings = m_value.GetArrayString();
1914         wxArrayString extraStrings;
1915 
1916         dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
1917 
1918         if ( dlg.ShowModal() == wxID_OK && choiceCount )
1919         {
1920             int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1921 
1922             wxArrayInt arrInt = dlg.GetSelections();
1923 
1924             wxVariant variant;
1925 
1926             // Strings that were not in list of choices
1927             wxArrayString value;
1928 
1929             // Translate string indices to strings
1930 
1931             unsigned int n;
1932             if ( userStringMode == 1 )
1933             {
1934                 for (n=0;n<extraStrings.size();n++)
1935                     value.push_back(extraStrings[n]);
1936             }
1937 
1938             unsigned int i;
1939             for ( i=0; i<arrInt.GetCount(); i++ )
1940                 value.Add(m_choices.GetLabel(arrInt.Item(i)));
1941 
1942             if ( userStringMode == 2 )
1943             {
1944                 for (n=0;n<extraStrings.size();n++)
1945                     value.push_back(extraStrings[n]);
1946             }
1947 
1948             variant = WXVARIANT(value);
1949 
1950             SetValueInEvent(variant);
1951 
1952             return true;
1953         }
1954     }
1955     return false;
1956 }
1957 
GetChoiceInfo(wxPGChoiceInfo * choiceinfo)1958 int wxMultiChoiceProperty::GetChoiceInfo( wxPGChoiceInfo* choiceinfo )
1959 {
1960     if ( choiceinfo )
1961         choiceinfo->m_choices = &m_choices;
1962     return -1;
1963 }
1964 
StringToValue(wxVariant & variant,const wxString & text,int) const1965 bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
1966 {
1967     wxArrayString arr;
1968 
1969     int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1970 
1971     WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
1972         if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
1973             arr.Add(token);
1974     WX_PG_TOKENIZER2_END()
1975 
1976     wxVariant v(arr);
1977     variant = v;
1978 
1979     return true;
1980 }
1981 
1982 #endif // wxUSE_CHOICEDLG
1983 
1984 
1985 // -----------------------------------------------------------------------
1986 // wxDateProperty
1987 // -----------------------------------------------------------------------
1988 
1989 #if wxUSE_DATETIME
1990 
1991 
1992 #if wxUSE_DATEPICKCTRL
1993     #define dtCtrl      DatePickerCtrl
1994 #else
1995     #define dtCtrl      TextCtrl
1996 #endif
1997 
1998 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
1999                                wxPGProperty,
2000                                wxDateTime,
2001                                const wxDateTime&,
2002                                dtCtrl)
2003 
2004 
2005 wxString wxDateProperty::ms_defaultDateFormat;
2006 
2007 
wxDateProperty(const wxString & label,const wxString & name,const wxDateTime & value)2008 wxDateProperty::wxDateProperty( const wxString& label,
2009                                 const wxString& name,
2010                                 const wxDateTime& value )
2011     : wxPGProperty(label,name)
2012 {
2013     //wxPGRegisterDefaultValueType(wxDateTime)
2014 
2015 #if wxUSE_DATEPICKCTRL
2016     wxPGRegisterEditorClass(DatePickerCtrl);
2017 
2018     m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
2019 #else
2020     m_dpStyle = 0;
2021 #endif
2022 
2023     SetValue( value );
2024 }
2025 
~wxDateProperty()2026 wxDateProperty::~wxDateProperty()
2027 {
2028 }
2029 
OnSetValue()2030 void wxDateProperty::OnSetValue()
2031 {
2032     //
2033     // Convert invalid dates to unspecified value
2034     if ( m_value.GetType() == wxT("datetime") )
2035     {
2036         if ( !m_value.GetDateTime().IsValid() )
2037             m_value.MakeNull();
2038     }
2039 }
2040 
StringToValue(wxVariant & variant,const wxString & text,int WXUNUSED (argFlags)) const2041 bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
2042                                     int WXUNUSED(argFlags) ) const
2043 {
2044     wxDateTime dt;
2045 
2046 #if wxCHECK_VERSION(3, 0, 0)
2047     const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL);
2048 #else
2049     const wxChar* c = dt.ParseFormat(text, wxDefaultDateTimeFormat);
2050 #endif
2051 
2052     if ( c )
2053     {
2054         variant = dt;
2055         return true;
2056     }
2057 
2058     return false;
2059 }
2060 
GetValueAsString(int argFlags) const2061 wxString wxDateProperty::GetValueAsString( int argFlags ) const
2062 {
2063     const wxChar* format = (const wxChar*) NULL;
2064 
2065     wxDateTime dateTime = m_value.GetDateTime();
2066 
2067     if ( !dateTime.IsValid() )
2068         return wxT("Invalid");
2069 
2070     if ( !ms_defaultDateFormat.length() )
2071     {
2072 #if wxUSE_DATEPICKCTRL
2073         bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
2074 #else
2075         bool showCentury = true;
2076 #endif
2077         ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
2078     }
2079 
2080     if ( m_format.length() &&
2081          !(argFlags & wxPG_FULL_VALUE) )
2082             format = m_format.c_str();
2083 
2084     // Determine default from locale
2085     // NB: This is really simple stuff, but can't figure anything
2086     //     better without proper support in wxLocale
2087     if ( !format )
2088         format = ms_defaultDateFormat.c_str();
2089 
2090     return dateTime.Format(format);
2091 }
2092 
DetermineDefaultDateFormat(bool showCentury)2093 wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
2094 {
2095     // This code is basicly copied from datectlg.cpp's SetFormat
2096     //
2097     wxString format;
2098 
2099     wxDateTime dt;
2100     dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2101     wxString str(dt.Format(wxT("%x")));
2102 
2103     const wxChar *p = str.c_str();
2104     while ( *p )
2105     {
2106         int n=wxAtoi(p);
2107         if (n == dt.GetDay())
2108         {
2109             format.Append(wxT("%d"));
2110             p += 2;
2111         }
2112         else if (n == (int)dt.GetMonth()+1)
2113         {
2114             format.Append(wxT("%m"));
2115             p += 2;
2116         }
2117         else if (n == dt.GetYear())
2118         {
2119             format.Append(wxT("%Y"));
2120             p += 4;
2121         }
2122         else if (n == (dt.GetYear() % 100))
2123         {
2124             if (showCentury)
2125                 format.Append(wxT("%Y"));
2126             else
2127                 format.Append(wxT("%y"));
2128             p += 2;
2129         }
2130         else
2131             format.Append(*p++);
2132     }
2133 
2134     return format;
2135 }
2136 
DoSetAttribute(const wxString & name,wxVariant & value)2137 bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2138 {
2139     if ( name == wxPG_DATE_FORMAT )
2140     {
2141         m_format = value.GetString();
2142         return true;
2143     }
2144     else if ( name == wxPG_DATE_PICKER_STYLE )
2145     {
2146         m_dpStyle = value.GetLong();
2147         ms_defaultDateFormat.clear();  // This may need recalculation
2148         return true;
2149     }
2150     return false;
2151 }
2152 
2153 #endif  // wxUSE_DATETIME
2154 
2155 
2156 // -----------------------------------------------------------------------
2157 // wxPropertyGridInterface
2158 // -----------------------------------------------------------------------
2159 
InitAllTypeHandlers()2160 void wxPropertyGridInterface::InitAllTypeHandlers()
2161 {
2162     //wxPG_INIT_REQUIRED_TYPE(wxColour)
2163     //wxPG_INIT_REQUIRED_TYPE(wxFont)
2164     //wxPG_INIT_REQUIRED_TYPE(wxArrayInt)
2165     //wxPG_INIT_REQUIRED_TYPE(wxColourPropertyValue)
2166 /*#if wxUSE_DATETIME
2167     wxPGRegisterDefaultValueType(wxDateTime)
2168 #endif*/
2169 }
2170 
2171 // -----------------------------------------------------------------------
2172 
RegisterAdditionalEditors()2173 void wxPropertyGridInterface::RegisterAdditionalEditors()
2174 {
2175 #if wxUSE_SPINBTN
2176     wxPGRegisterEditorClass(SpinCtrl);
2177 #endif
2178 #if wxUSE_DATEPICKCTRL
2179     wxPGRegisterEditorClass(DatePickerCtrl);
2180 #endif
2181 }
2182 
2183 // -----------------------------------------------------------------------
2184 
2185 #endif // wxPG_INCLUDE_ADVPROPS
2186