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