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