Fixed a VC6 warning (hopefully)
[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 = (wxDateProperty*) property;
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, wxWindow* wnd ) const
494 {
495 wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
496 wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
497
498 // We assume that property's data type is 'int' (or something similar),
499 // thus allowing us to get raw, unchecked value via DoGetValue.
500 ctrl->SetValue( property->GetValue().GetDateTime() );
501 }
502
503 // Control's events are redirected here
504 bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid),
505 wxPGProperty* WXUNUSED(property),
506 wxWindow* WXUNUSED(wnd),
507 wxEvent& event ) const
508 {
509 if ( event.GetEventType() == wxEVT_DATE_CHANGED )
510 return true;
511
512 return false;
513 }
514
515 bool wxPGDatePickerCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* WXUNUSED(property), wxWindow* wnd ) const
516 {
517 wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd;
518 wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) );
519
520 variant = ctrl->GetValue();
521
522 return true;
523 }
524
525 void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* WXUNUSED(wnd) ) const
526 {
527 // TODO?
528 //wxDateProperty* prop = (wxDateProperty*) property;
529 //ctrl->SetValue(?);
530 }
531
532 #endif // wxUSE_DATEPICKCTRL
533
534
535 // -----------------------------------------------------------------------
536 // wxFontProperty
537 // -----------------------------------------------------------------------
538
539 #include "wx/fontdlg.h"
540 #include "wx/fontenum.h"
541
542 static const wxChar* gs_fp_es_family_labels[] = {
543 wxT("Default"), wxT("Decorative"),
544 wxT("Roman"), wxT("Script"),
545 wxT("Swiss"), wxT("Modern"),
546 (const wxChar*) NULL
547 };
548
549 static long gs_fp_es_family_values[] = {
550 wxDEFAULT, wxDECORATIVE,
551 wxROMAN, wxSCRIPT,
552 wxSWISS, wxMODERN
553 };
554
555 static const wxChar* gs_fp_es_style_labels[] = {
556 wxT("Normal"),
557 wxT("Slant"),
558 wxT("Italic"),
559 (const wxChar*) NULL
560 };
561
562 static long gs_fp_es_style_values[] = {
563 wxNORMAL,
564 wxSLANT,
565 wxITALIC
566 };
567
568 static const wxChar* gs_fp_es_weight_labels[] = {
569 wxT("Normal"),
570 wxT("Light"),
571 wxT("Bold"),
572 (const wxChar*) NULL
573 };
574
575 static long gs_fp_es_weight_values[] = {
576 wxNORMAL,
577 wxLIGHT,
578 wxBOLD
579 };
580
581 // Class body is in advprops.h
582
583
584 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxPGProperty,
585 wxFont,const wxFont&,TextCtrlAndButton)
586
587
588 wxFontProperty::wxFontProperty( const wxString& label, const wxString& name,
589 const wxFont& value )
590 : wxPGProperty(label,name)
591 {
592 SetValue(WXVARIANT(value));
593
594 // Initialize font family choices list
595 if ( !wxPGGlobalVars->m_fontFamilyChoices )
596 {
597 wxArrayString faceNames = wxFontEnumerator::GetFacenames();
598
599 faceNames.Sort();
600
601 wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames);
602 }
603
604 wxString emptyString(wxEmptyString);
605
606 wxFont font;
607 font << m_value;
608
609 SetParentalType(wxPG_PROP_AGGREGATE);
610
611 AddChild( new wxIntProperty( _("Point Size"), wxS("Point Size"),(long)font.GetPointSize() ) );
612
613 AddChild( new wxEnumProperty(_("Family"), wxS("PointSize"),
614 gs_fp_es_family_labels,gs_fp_es_family_values,
615 font.GetFamily()) );
616
617 wxString faceName = font.GetFaceName();
618 // If font was not in there, add it now
619 if ( faceName.length() &&
620 wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND )
621 wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName);
622
623 wxPGProperty* p = new wxEnumProperty(_("Face Name"), wxS("Face Name"),
624 *wxPGGlobalVars->m_fontFamilyChoices);
625
626 p->SetValueFromString(faceName, wxPG_FULL_VALUE);
627
628 AddChild( p );
629
630 AddChild( new wxEnumProperty(_("Style"), wxS("Style"),
631 gs_fp_es_style_labels,gs_fp_es_style_values,font.GetStyle()) );
632
633 AddChild( new wxEnumProperty(_("Weight"), wxS("Weight"),
634 gs_fp_es_weight_labels,gs_fp_es_weight_values,font.GetWeight()) );
635
636 AddChild( new wxBoolProperty(_("Underlined"), wxS("Underlined"),
637 font.GetUnderlined()) );
638 }
639
640 wxFontProperty::~wxFontProperty() { }
641
642 void wxFontProperty::OnSetValue()
643 {
644 wxFont font;
645 font << m_value;
646
647 if ( !font.Ok() )
648 {
649 font = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL);
650 m_value << font;
651 }
652 }
653
654 wxString wxFontProperty::ValueToString( wxVariant& value,
655 int argFlags ) const
656 {
657 return wxPGProperty::ValueToString(value, argFlags);
658 }
659
660 bool wxFontProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary),
661 wxEvent& event )
662 {
663 if ( propgrid->IsMainButtonEvent(event) )
664 {
665 // Update value from last minute changes
666 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
667
668 wxFontData data;
669 wxFont font;
670 font << useValue;
671 data.SetInitialFont( font );
672 data.SetColour(*wxBLACK);
673
674 wxFontDialog dlg(propgrid, data);
675 if ( dlg.ShowModal() == wxID_OK )
676 {
677 propgrid->EditorsValueWasModified();
678
679 wxVariant variant;
680 variant << dlg.GetFontData().GetChosenFont();
681 SetValueInEvent( variant );
682 return true;
683 }
684 }
685 return false;
686 }
687
688 void wxFontProperty::RefreshChildren()
689 {
690 if ( !GetChildCount() ) return;
691 wxFont font;
692 font << m_value;
693 Item(0)->SetValue( (long)font.GetPointSize() );
694 Item(1)->SetValue( (long)font.GetFamily() );
695 Item(2)->SetValueFromString( font.GetFaceName(), wxPG_FULL_VALUE );
696 Item(3)->SetValue( (long)font.GetStyle() );
697 Item(4)->SetValue( (long)font.GetWeight() );
698 Item(5)->SetValue( font.GetUnderlined() );
699 }
700
701 void wxFontProperty::ChildChanged( wxVariant& thisValue, int ind, wxVariant& childValue ) const
702 {
703 wxFont font;
704 font << thisValue;
705
706 if ( ind == 0 )
707 {
708 font.SetPointSize( wxPGVariantToInt(childValue) );
709 }
710 else if ( ind == 1 )
711 {
712 int fam = childValue.GetLong();
713 if ( fam < wxDEFAULT ||
714 fam > wxTELETYPE )
715 fam = wxDEFAULT;
716 font.SetFamily( fam );
717 }
718 else if ( ind == 2 )
719 {
720 wxString faceName;
721 int faceIndex = childValue.GetLong();
722
723 if ( faceIndex >= 0 )
724 faceName = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(faceIndex);
725
726 font.SetFaceName( faceName );
727 }
728 else if ( ind == 3 )
729 {
730 int st = childValue.GetLong();
731 if ( st != wxFONTSTYLE_NORMAL &&
732 st != wxFONTSTYLE_SLANT &&
733 st != wxFONTSTYLE_ITALIC )
734 st = wxFONTWEIGHT_NORMAL;
735 font.SetStyle( st );
736 }
737 else if ( ind == 4 )
738 {
739 int wt = childValue.GetLong();
740 if ( wt != wxFONTWEIGHT_NORMAL &&
741 wt != wxFONTWEIGHT_LIGHT &&
742 wt != wxFONTWEIGHT_BOLD )
743 wt = wxFONTWEIGHT_NORMAL;
744 font.SetWeight( wt );
745 }
746 else if ( ind == 5 )
747 {
748 font.SetUnderlined( childValue.GetBool() );
749 }
750
751 thisValue << font;
752 }
753
754 /*
755 wxSize wxFontProperty::OnMeasureImage() const
756 {
757 return wxSize(-1,-1);
758 }
759
760 void wxFontProperty::OnCustomPaint(wxDC& dc,
761 const wxRect& rect,
762 wxPGPaintData& paintData)
763 {
764 wxString drawFace;
765 if ( paintData.m_choiceItem >= 0 )
766 drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem);
767 else
768 drawFace = m_value_wxFont.GetFaceName();
769
770 if ( drawFace.length() )
771 {
772 // Draw the background
773 dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) );
774 //dc.SetBrush( *wxWHITE_BRUSH );
775 //dc.SetPen( *wxMEDIUM_GREY_PEN );
776 dc.DrawRectangle( rect );
777
778 wxFont oldFont = dc.GetFont();
779 wxFont drawFont(oldFont.GetPointSize(),
780 wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace);
781 dc.SetFont(drawFont);
782
783 dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) );
784 dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 );
785
786 dc.SetFont(oldFont);
787 }
788 else
789 {
790 // No file - just draw a white box
791 dc.SetBrush ( *wxWHITE_BRUSH );
792 dc.DrawRectangle ( rect );
793 }
794 }
795 */
796
797
798 // -----------------------------------------------------------------------
799 // wxSystemColourProperty
800 // -----------------------------------------------------------------------
801
802 // wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1
803 #define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2
804
805 #include "wx/colordlg.h"
806
807 //#define wx_cp_es_syscolours_len 25
808 static const wxChar* gs_cp_es_syscolour_labels[] = {
809 wxT("AppWorkspace"),
810 wxT("ActiveBorder"),
811 wxT("ActiveCaption"),
812 wxT("ButtonFace"),
813 wxT("ButtonHighlight"),
814 wxT("ButtonShadow"),
815 wxT("ButtonText"),
816 wxT("CaptionText"),
817 wxT("ControlDark"),
818 wxT("ControlLight"),
819 wxT("Desktop"),
820 wxT("GrayText"),
821 wxT("Highlight"),
822 wxT("HighlightText"),
823 wxT("InactiveBorder"),
824 wxT("InactiveCaption"),
825 wxT("InactiveCaptionText"),
826 wxT("Menu"),
827 wxT("Scrollbar"),
828 wxT("Tooltip"),
829 wxT("TooltipText"),
830 wxT("Window"),
831 wxT("WindowFrame"),
832 wxT("WindowText"),
833 wxT("Custom"),
834 (const wxChar*) NULL
835 };
836
837 static long gs_cp_es_syscolour_values[] = {
838 wxSYS_COLOUR_APPWORKSPACE,
839 wxSYS_COLOUR_ACTIVEBORDER,
840 wxSYS_COLOUR_ACTIVECAPTION,
841 wxSYS_COLOUR_BTNFACE,
842 wxSYS_COLOUR_BTNHIGHLIGHT,
843 wxSYS_COLOUR_BTNSHADOW,
844 wxSYS_COLOUR_BTNTEXT ,
845 wxSYS_COLOUR_CAPTIONTEXT,
846 wxSYS_COLOUR_3DDKSHADOW,
847 wxSYS_COLOUR_3DLIGHT,
848 wxSYS_COLOUR_BACKGROUND,
849 wxSYS_COLOUR_GRAYTEXT,
850 wxSYS_COLOUR_HIGHLIGHT,
851 wxSYS_COLOUR_HIGHLIGHTTEXT,
852 wxSYS_COLOUR_INACTIVEBORDER,
853 wxSYS_COLOUR_INACTIVECAPTION,
854 wxSYS_COLOUR_INACTIVECAPTIONTEXT,
855 wxSYS_COLOUR_MENU,
856 wxSYS_COLOUR_SCROLLBAR,
857 wxSYS_COLOUR_INFOBK,
858 wxSYS_COLOUR_INFOTEXT,
859 wxSYS_COLOUR_WINDOW,
860 wxSYS_COLOUR_WINDOWFRAME,
861 wxSYS_COLOUR_WINDOWTEXT,
862 wxPG_COLOUR_CUSTOM
863 };
864
865
866 IMPLEMENT_VARIANT_OBJECT_EXPORTED_SHALLOWCMP(wxColourPropertyValue, WXDLLIMPEXP_PROPGRID)
867
868
869 // Class body is in advprops.h
870
871 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty,
872 wxColourPropertyValue,const wxColourPropertyValue&,Choice)
873
874
875 void wxSystemColourProperty::Init( int type, const wxColour& colour )
876 {
877 wxColourPropertyValue cpv;
878
879 if ( colour.Ok() )
880 cpv.Init( type, colour );
881 else
882 cpv.Init( type, *wxWHITE );
883
884 m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed.
885
886 m_value << cpv;
887
888 OnSetValue();
889 }
890
891
892 static wxPGChoices gs_wxSystemColourProperty_choicesCache;
893
894
895 wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
896 const wxColourPropertyValue& value )
897 : wxEnumProperty( label,
898 name,
899 gs_cp_es_syscolour_labels,
900 gs_cp_es_syscolour_values,
901 &gs_wxSystemColourProperty_choicesCache )
902 {
903 if ( &value )
904 Init( value.m_type, value.m_colour );
905 else
906 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
907 }
908
909
910 wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
911 const wxChar** labels, const long* values, wxPGChoices* choicesCache,
912 const wxColourPropertyValue& value )
913 : wxEnumProperty( label, name, labels, values, choicesCache )
914 {
915 if ( &value )
916 Init( value.m_type, value.m_colour );
917 else
918 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
919 }
920
921
922 wxSystemColourProperty::wxSystemColourProperty( const wxString& label, const wxString& name,
923 const wxChar** labels, const long* values, wxPGChoices* choicesCache,
924 const wxColour& value )
925 : wxEnumProperty( label, name, labels, values, choicesCache )
926 {
927 if ( &value )
928 Init( wxPG_COLOUR_CUSTOM, value );
929 else
930 Init( wxPG_COLOUR_CUSTOM, *wxWHITE );
931 }
932
933
934 wxSystemColourProperty::~wxSystemColourProperty() { }
935
936
937 wxColourPropertyValue wxSystemColourProperty::GetVal( const wxVariant* pVariant ) const
938 {
939 if ( !pVariant )
940 pVariant = &m_value;
941
942 if ( pVariant->IsNull() )
943 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
944
945 if ( pVariant->GetType() == wxS("wxColourPropertyValue") )
946 {
947 wxColourPropertyValue v;
948 v << *pVariant;
949 return v;
950 }
951
952 wxColour col;
953 bool variantProcessed = true;
954
955 if ( pVariant->GetType() == wxS("wxColour*") )
956 {
957 wxColour* pCol = wxStaticCast(pVariant->GetWxObjectPtr(), wxColour);
958 col = *pCol;
959 }
960 else if ( pVariant->GetType() == wxS("wxColour") )
961 {
962 col << *pVariant;
963 }
964 else if ( pVariant->GetType() == wxArrayInt_VariantType )
965 {
966 // This code is mostly needed for wxPython bindings, which
967 // may offer tuple of integers as colour value.
968 wxArrayInt arr;
969 arr << *pVariant;
970
971 if ( arr.size() >= 3 )
972 {
973 int r, g, b;
974 int a = 255;
975
976 r = arr[0];
977 g = arr[1];
978 b = arr[2];
979 if ( arr.size() >= 4 )
980 a = arr[3];
981
982 col = wxColour(r, g, b, a);
983 }
984 else
985 {
986 variantProcessed = false;
987 }
988 }
989 else
990 {
991 variantProcessed = false;
992 }
993
994 if ( !variantProcessed )
995 return wxColourPropertyValue(wxPG_COLOUR_UNSPECIFIED, wxColour());
996
997 wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
998
999 int colInd = ColToInd(col);
1000 if ( colInd != wxNOT_FOUND )
1001 v2.m_type = colInd;
1002
1003 return v2;
1004 }
1005
1006 wxVariant wxSystemColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1007 {
1008 wxVariant variant;
1009 variant << v;
1010 return variant;
1011 }
1012
1013 int wxSystemColourProperty::ColToInd( const wxColour& colour ) const
1014 {
1015 size_t i;
1016 size_t i_max = m_choices.GetCount() - 1;
1017
1018 for ( i=0; i<i_max; i++ )
1019 {
1020 int ind = m_choices[i].GetValue();
1021
1022 if ( colour == GetColour(ind) )
1023 {
1024 /*wxLogDebug(wxT("%s(%s): Index %i for ( getcolour(%i,%i,%i), colour(%i,%i,%i))"),
1025 GetClassName(),GetLabel().c_str(),
1026 (int)i,(int)GetColour(ind).Red(),(int)GetColour(ind).Green(),(int)GetColour(ind).Blue(),
1027 (int)colour.Red(),(int)colour.Green(),(int)colour.Blue());*/
1028 return ind;
1029 }
1030 }
1031 return wxNOT_FOUND;
1032 }
1033
1034 void wxSystemColourProperty::OnSetValue()
1035 {
1036 // Convert from generic wxobject ptr to wxPGVariantDataColour
1037 if ( m_value.GetType() == wxS("wxColour*") )
1038 {
1039 wxColour* pCol = wxStaticCast(m_value.GetWxObjectPtr(), wxColour);
1040 m_value << *pCol;
1041 }
1042
1043 wxColourPropertyValue val = GetVal(&m_value);
1044
1045 if ( val.m_type == wxPG_COLOUR_UNSPECIFIED )
1046 {
1047 m_value.MakeNull();
1048 return;
1049 }
1050 else
1051 {
1052
1053 if ( val.m_type < wxPG_COLOUR_WEB_BASE )
1054 val.m_colour = GetColour( val.m_type );
1055
1056 m_value = TranslateVal(val);
1057 }
1058
1059 int ind = wxNOT_FOUND;
1060
1061 if ( m_value.GetType() == wxS("wxColourPropertyValue") )
1062 {
1063 wxColourPropertyValue cpv;
1064 cpv << m_value;
1065 wxColour col = cpv.m_colour;
1066
1067 if ( !col.Ok() )
1068 {
1069 SetValueToUnspecified();
1070 SetIndex(wxNOT_FOUND);
1071 return;
1072 }
1073
1074 if ( cpv.m_type < wxPG_COLOUR_WEB_BASE )
1075 {
1076 ind = GetIndexForValue(cpv.m_type);
1077 }
1078 else
1079 {
1080 cpv.m_type = wxPG_COLOUR_CUSTOM;
1081 ind = GetCustomColourIndex();
1082 }
1083 }
1084 else
1085 {
1086 wxColour col;
1087 col << m_value;
1088
1089 if ( !col.Ok() )
1090 {
1091 SetValueToUnspecified();
1092 SetIndex(wxNOT_FOUND);
1093 return;
1094 }
1095
1096 ind = ColToInd(col);
1097
1098 if ( ind == wxNOT_FOUND )
1099 ind = GetCustomColourIndex();
1100 }
1101
1102 SetIndex(ind);
1103 }
1104
1105
1106 wxColour wxSystemColourProperty::GetColour( int index ) const
1107 {
1108 return wxSystemSettings::GetColour( (wxSystemColour)index );
1109 }
1110
1111 wxString wxSystemColourProperty::ColourToString( const wxColour& col, int index ) const
1112 {
1113 if ( index == wxNOT_FOUND )
1114 return wxString::Format(wxT("(%i,%i,%i)"),
1115 (int)col.Red(),
1116 (int)col.Green(),
1117 (int)col.Blue());
1118 else
1119 return m_choices.GetLabel(index);
1120 }
1121
1122 wxString wxSystemColourProperty::ValueToString( wxVariant& value,
1123 int argFlags ) const
1124 {
1125 wxColourPropertyValue val = GetVal(&value);
1126
1127 int index;
1128
1129 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1130 {
1131 // GetIndex() only works reliably if wxPG_VALUE_IS_CURRENT flag is set,
1132 // but we should use it whenever possible.
1133 index = GetIndex();
1134
1135 // If custom colour was selected, use invalid index, so that
1136 // ColourToString() will return properly formatted colour text.
1137 if ( index == GetCustomColourIndex() )
1138 index = wxNOT_FOUND;
1139 }
1140 else
1141 {
1142 index = m_choices.Index(val.m_type);
1143 }
1144
1145 return ColourToString(val.m_colour, index);
1146 }
1147
1148
1149 wxSize wxSystemColourProperty::OnMeasureImage( int ) const
1150 {
1151 return wxPG_DEFAULT_IMAGE_SIZE;
1152 }
1153
1154
1155 int wxSystemColourProperty::GetCustomColourIndex() const
1156 {
1157 return m_choices.GetCount() - 1;
1158 }
1159
1160
1161 bool wxSystemColourProperty::QueryColourFromUser( wxVariant& variant ) const
1162 {
1163 wxASSERT( m_value.GetType() != wxPG_VARIANT_TYPE_STRING );
1164 bool res = false;
1165
1166 wxPropertyGrid* propgrid = GetGrid();
1167 wxASSERT( propgrid );
1168
1169 // Must only occur when user triggers event
1170 if ( !(propgrid->GetInternalFlags() & wxPG_FL_IN_HANDLECUSTOMEDITOREVENT) )
1171 return res;
1172
1173 wxColourPropertyValue val = GetVal();
1174
1175 val.m_type = wxPG_COLOUR_CUSTOM;
1176
1177 wxColourData data;
1178 data.SetChooseFull(true);
1179 data.SetColour(val.m_colour);
1180 int i;
1181 for ( i = 0; i < 16; i++)
1182 {
1183 wxColour colour(i*16, i*16, i*16);
1184 data.SetCustomColour(i, colour);
1185 }
1186
1187 wxColourDialog dialog(propgrid, &data);
1188 if ( dialog.ShowModal() == wxID_OK )
1189 {
1190 wxColourData retData = dialog.GetColourData();
1191 val.m_colour = retData.GetColour();
1192
1193 variant = DoTranslateVal(val);
1194
1195 SetValueInEvent(variant);
1196
1197 res = true;
1198 }
1199
1200 return res;
1201 }
1202
1203
1204 bool wxSystemColourProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argFlags) ) const
1205 {
1206 int index = number;
1207 int type = m_choices.GetValue(index);
1208
1209 if ( type == wxPG_COLOUR_CUSTOM )
1210 {
1211 QueryColourFromUser(variant);
1212 }
1213 else
1214 {
1215 variant = TranslateVal( type, GetColour(type) );
1216 }
1217
1218 return true;
1219 }
1220
1221 // Need to do some extra event handling.
1222 bool wxSystemColourProperty::OnEvent( wxPropertyGrid* propgrid, wxWindow* WXUNUSED(primary), wxEvent& event )
1223 {
1224 if ( propgrid->IsMainButtonEvent(event) )
1225 {
1226 // We need to handle button click in case editor has been
1227 // switched to one that has wxButton as well.
1228 wxVariant variant;
1229 if ( QueryColourFromUser(variant) )
1230 return true;
1231 }
1232 return false;
1233 }
1234
1235 /*class wxPGColourPropertyRenderer : public wxPGDefaultRenderer
1236 {
1237 public:
1238 virtual void Render( wxDC& dc, const wxRect& rect,
1239 const wxPropertyGrid* propertyGrid, wxPGProperty* property,
1240 int WXUNUSED(column), int item, int WXUNUSED(flags) ) const
1241 {
1242 wxASSERT( property->IsKindOf(CLASSINFO(wxSystemColourProperty)) );
1243 wxSystemColourProperty* prop = wxStaticCast(property, wxSystemColourProperty);
1244
1245 dc.SetPen(*wxBLACK_PEN);
1246 if ( item >= 0 &&
1247 ( item < (int)(GetCustomColourIndex) || (prop->HasFlag(wxPG_PROP_HIDE_CUSTOM_COLOUR)))
1248 )
1249 {
1250 int colInd;
1251 const wxArrayInt& values = prop->GetValues();
1252 if ( values.GetChildCount() )
1253 colInd = values[item];
1254 else
1255 colInd = item;
1256 dc.SetBrush( wxColour( prop->GetColour( colInd ) ) );
1257 }
1258 else if ( !prop->IsValueUnspecified() )
1259 dc.SetBrush( prop->GetVal().m_colour );
1260 else
1261 dc.SetBrush( *wxWHITE );
1262
1263 wxRect imageRect = propertyGrid->GetImageRect(property, item);
1264 wxLogDebug(wxT("%i, %i"),imageRect.x,imageRect.y);
1265 dc.DrawRectangle( rect.x+imageRect.x, rect.y+imageRect.y,
1266 imageRect.width, imageRect.height );
1267
1268 wxString text;
1269 if ( item == -1 )
1270 text = property->GetValueAsString();
1271 else
1272 text = property->GetChoiceString(item);
1273 DrawText( dc, rect, imageRect.width, text );
1274 }
1275 protected:
1276 };
1277
1278 wxPGColourPropertyRenderer g_wxPGColourPropertyRenderer;
1279
1280 wxPGCellRenderer* wxSystemColourProperty::GetCellRenderer( int column ) const
1281 {
1282 if ( column == 1 )
1283 return &g_wxPGColourPropertyRenderer;
1284 return wxEnumProperty::GetCellRenderer(column);
1285 }*/
1286
1287 void wxSystemColourProperty::OnCustomPaint( wxDC& dc, const wxRect& rect,
1288 wxPGPaintData& paintdata )
1289 {
1290 wxColour col;
1291
1292 if ( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < (int)m_choices.GetCount() &&
1293 paintdata.m_choiceItem != GetCustomColourIndex() )
1294 {
1295 int colInd = m_choices[paintdata.m_choiceItem].GetValue();
1296 col = GetColour( colInd );
1297 }
1298 else if ( !IsValueUnspecified() )
1299 {
1300 col = GetVal().m_colour;
1301 }
1302
1303 if ( col.Ok() )
1304 {
1305 dc.SetBrush(col);
1306 dc.DrawRectangle(rect);
1307 }
1308 }
1309
1310
1311 bool wxSystemColourProperty::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const
1312 {
1313 //
1314 // Accept colour format "[Name] [(R,G,B)]"
1315 // Name takes precedence.
1316 //
1317 wxString colourName;
1318 wxString colourRGB;
1319
1320 int ppos = text.Find(wxT("("));
1321
1322 if ( ppos == wxNOT_FOUND )
1323 {
1324 colourName = text;
1325 }
1326 else
1327 {
1328 colourName = text.substr(0, ppos);
1329 colourRGB = text.substr(ppos, text.length()-ppos);
1330 }
1331
1332 // Strip spaces from extremities
1333 colourName.Trim(true);
1334 colourName.Trim(false);
1335 colourRGB.Trim(true);
1336
1337 // Validate colourRGB string - (1,1,1) is shortest allowed
1338 if ( colourRGB.length() < 7 )
1339 colourRGB.clear();
1340
1341 if ( colourRGB.length() == 0 && m_choices.GetCount() &&
1342 colourName == m_choices.GetLabel(GetCustomColourIndex()) )
1343 {
1344 if ( !(argFlags & wxPG_EDITABLE_VALUE ))
1345 {
1346 // This really should not occurr...
1347 // wxASSERT(false);
1348 ResetNextIndex();
1349 return false;
1350 }
1351
1352 QueryColourFromUser(value);
1353 }
1354 else
1355 {
1356 wxColourPropertyValue val;
1357
1358 bool done = false;
1359
1360 if ( colourName.length() )
1361 {
1362 // Try predefined colour first
1363 bool res = wxEnumProperty::StringToValue(value, colourName, argFlags);
1364 if ( res && GetIndex() >= 0 )
1365 {
1366 val.m_type = GetIndex();
1367 if ( val.m_type < m_choices.GetCount() )
1368 val.m_type = m_choices[val.m_type].GetValue();
1369
1370 // Get proper colour for type.
1371 val.m_colour = GetColour(val.m_type);
1372
1373 done = true;
1374 }
1375 }
1376 if ( colourRGB.length() && !done )
1377 {
1378 // Then check custom colour.
1379 val.m_type = wxPG_COLOUR_CUSTOM;
1380
1381 int r = -1, g = -1, b = -1;
1382 wxSscanf(colourRGB.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b);
1383
1384 if ( r >= 0 && r <= 255 &&
1385 g >= 0 && g <= 255 &&
1386 b >= 0 && b <= 255 )
1387 {
1388 val.m_colour.Set(r,g,b);
1389
1390 done = true;
1391 }
1392 }
1393
1394 if ( !done )
1395 {
1396 ResetNextIndex();
1397 return false;
1398 }
1399
1400 value = DoTranslateVal(val);
1401 }
1402
1403 return true;
1404 }
1405
1406
1407 bool wxSystemColourProperty::DoSetAttribute( const wxString& name, wxVariant& value )
1408 {
1409 if ( name == wxPG_COLOUR_ALLOW_CUSTOM )
1410 {
1411 int ival = wxPGVariantToInt(value);
1412
1413 SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties
1414
1415 if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1416 {
1417 // Show custom choice
1418 m_choices.Insert(wxT("Custom"), GetCustomColourIndex(), wxPG_COLOUR_CUSTOM);
1419 m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR);
1420 }
1421 else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) )
1422 {
1423 // Hide custom choice
1424 m_choices.RemoveAt(GetCustomColourIndex());
1425 m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR;
1426 }
1427 return true;
1428 }
1429 return false;
1430 }
1431
1432
1433 // -----------------------------------------------------------------------
1434 // wxColourProperty
1435 // -----------------------------------------------------------------------
1436
1437 static const wxChar* gs_cp_es_normcolour_labels[] = {
1438 wxT("Black"),
1439 wxT("Maroon"),
1440 wxT("Navy"),
1441 wxT("Purple"),
1442 wxT("Teal"),
1443 wxT("Gray"),
1444 wxT("Green"),
1445 wxT("Olive"),
1446 wxT("Brown"),
1447 wxT("Blue"),
1448 wxT("Fuchsia"),
1449 wxT("Red"),
1450 wxT("Orange"),
1451 wxT("Silver"),
1452 wxT("Lime"),
1453 wxT("Aqua"),
1454 wxT("Yellow"),
1455 wxT("White"),
1456 wxT("Custom"),
1457 (const wxChar*) NULL
1458 };
1459
1460 static unsigned long gs_cp_es_normcolour_colours[] = {
1461 wxPG_COLOUR(0,0,0),
1462 wxPG_COLOUR(128,0,0),
1463 wxPG_COLOUR(0,0,128),
1464 wxPG_COLOUR(128,0,128),
1465 wxPG_COLOUR(0,128,128),
1466 wxPG_COLOUR(128,128,128),
1467 wxPG_COLOUR(0,128,0),
1468 wxPG_COLOUR(128,128,0),
1469 wxPG_COLOUR(166,124,81),
1470 wxPG_COLOUR(0,0,255),
1471 wxPG_COLOUR(255,0,255),
1472 wxPG_COLOUR(255,0,0),
1473 wxPG_COLOUR(247,148,28),
1474 wxPG_COLOUR(192,192,192),
1475 wxPG_COLOUR(0,255,0),
1476 wxPG_COLOUR(0,255,255),
1477 wxPG_COLOUR(255,255,0),
1478 wxPG_COLOUR(255,255,255),
1479 wxPG_COLOUR(0,0,0)
1480 };
1481
1482 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxColourProperty, wxSystemColourProperty,
1483 wxColour, const wxColour&, TextCtrlAndButton)
1484
1485 static wxPGChoices gs_wxColourProperty_choicesCache;
1486
1487 wxColourProperty::wxColourProperty( const wxString& label,
1488 const wxString& name,
1489 const wxColour& value )
1490 : wxSystemColourProperty(label, name, gs_cp_es_normcolour_labels,
1491 NULL,
1492 &gs_wxColourProperty_choicesCache, value )
1493 {
1494 Init( value );
1495
1496 m_flags |= wxPG_PROP_TRANSLATE_CUSTOM;
1497 }
1498
1499 wxColourProperty::~wxColourProperty()
1500 {
1501 }
1502
1503 void wxColourProperty::Init( wxColour colour )
1504 {
1505 if ( !colour.Ok() )
1506 colour = *wxWHITE;
1507 wxVariant variant;
1508 variant << colour;
1509 m_value = variant;
1510 int ind = ColToInd(colour);
1511 if ( ind < 0 )
1512 ind = m_choices.GetCount() - 1;
1513 SetIndex( ind );
1514 }
1515
1516 wxString wxColourProperty::ValueToString( wxVariant& value,
1517 int argFlags ) const
1518 {
1519 const wxPGEditor* editor = GetEditorClass();
1520 if ( editor != wxPGEditor_Choice &&
1521 editor != wxPGEditor_ChoiceAndButton &&
1522 editor != wxPGEditor_ComboBox )
1523 argFlags |= wxPG_PROPERTY_SPECIFIC;
1524
1525 return wxSystemColourProperty::ValueToString(value, argFlags);
1526 }
1527
1528 wxColour wxColourProperty::GetColour( int index ) const
1529 {
1530 return gs_cp_es_normcolour_colours[m_choices.GetValue(index)];
1531 }
1532
1533 wxVariant wxColourProperty::DoTranslateVal( wxColourPropertyValue& v ) const
1534 {
1535 wxVariant variant;
1536 variant << v.m_colour;
1537 return variant;
1538 }
1539
1540 // -----------------------------------------------------------------------
1541 // wxCursorProperty
1542 // -----------------------------------------------------------------------
1543
1544 #define wxPG_CURSOR_IMAGE_WIDTH 32
1545
1546 #define NUM_CURSORS 28
1547
1548 //#define wx_cp_es_syscursors_len 28
1549 static const wxChar* gs_cp_es_syscursors_labels[NUM_CURSORS+1] = {
1550 wxT("Default"),
1551 wxT("Arrow"),
1552 wxT("Right Arrow"),
1553 wxT("Blank"),
1554 wxT("Bullseye"),
1555 wxT("Character"),
1556 wxT("Cross"),
1557 wxT("Hand"),
1558 wxT("I-Beam"),
1559 wxT("Left Button"),
1560 wxT("Magnifier"),
1561 wxT("Middle Button"),
1562 wxT("No Entry"),
1563 wxT("Paint Brush"),
1564 wxT("Pencil"),
1565 wxT("Point Left"),
1566 wxT("Point Right"),
1567 wxT("Question Arrow"),
1568 wxT("Right Button"),
1569 wxT("Sizing NE-SW"),
1570 wxT("Sizing N-S"),
1571 wxT("Sizing NW-SE"),
1572 wxT("Sizing W-E"),
1573 wxT("Sizing"),
1574 wxT("Spraycan"),
1575 wxT("Wait"),
1576 wxT("Watch"),
1577 wxT("Wait Arrow"),
1578 (const wxChar*) NULL
1579 };
1580
1581 static long gs_cp_es_syscursors_values[NUM_CURSORS] = {
1582 wxCURSOR_NONE,
1583 wxCURSOR_ARROW,
1584 wxCURSOR_RIGHT_ARROW,
1585 wxCURSOR_BLANK,
1586 wxCURSOR_BULLSEYE,
1587 wxCURSOR_CHAR,
1588 wxCURSOR_CROSS,
1589 wxCURSOR_HAND,
1590 wxCURSOR_IBEAM,
1591 wxCURSOR_LEFT_BUTTON,
1592 wxCURSOR_MAGNIFIER,
1593 wxCURSOR_MIDDLE_BUTTON,
1594 wxCURSOR_NO_ENTRY,
1595 wxCURSOR_PAINT_BRUSH,
1596 wxCURSOR_PENCIL,
1597 wxCURSOR_POINT_LEFT,
1598 wxCURSOR_POINT_RIGHT,
1599 wxCURSOR_QUESTION_ARROW,
1600 wxCURSOR_RIGHT_BUTTON,
1601 wxCURSOR_SIZENESW,
1602 wxCURSOR_SIZENS,
1603 wxCURSOR_SIZENWSE,
1604 wxCURSOR_SIZEWE,
1605 wxCURSOR_SIZING,
1606 wxCURSOR_SPRAYCAN,
1607 wxCURSOR_WAIT,
1608 wxCURSOR_WATCH,
1609 wxCURSOR_ARROWWAIT
1610 };
1611
1612 IMPLEMENT_DYNAMIC_CLASS(wxCursorProperty, wxEnumProperty)
1613
1614 wxCursorProperty::wxCursorProperty( const wxString& label, const wxString& name,
1615 int value )
1616 : wxEnumProperty( label,
1617 name,
1618 gs_cp_es_syscursors_labels,
1619 gs_cp_es_syscursors_values,
1620 value )
1621 {
1622 m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed.
1623 }
1624
1625 wxCursorProperty::~wxCursorProperty()
1626 {
1627 }
1628
1629 wxSize wxCursorProperty::OnMeasureImage( int item ) const
1630 {
1631 #if wxPG_CAN_DRAW_CURSOR
1632 if ( item != -1 && item < NUM_CURSORS )
1633 return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH);
1634 #else
1635 wxUnusedVar(item);
1636 #endif
1637 return wxSize(0,0);
1638 }
1639
1640 #if wxPG_CAN_DRAW_CURSOR
1641
1642 void wxCursorProperty::OnCustomPaint( wxDC& dc,
1643 const wxRect& rect,
1644 wxPGPaintData& paintdata )
1645 {
1646 // Background brush
1647 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
1648
1649 if ( paintdata.m_choiceItem >= 0 )
1650 {
1651 dc.DrawRectangle( rect );
1652
1653 if ( paintdata.m_choiceItem < NUM_CURSORS )
1654 {
1655 wxStockCursor cursorIndex =
1656 (wxStockCursor) gs_cp_es_syscursors_values[paintdata.m_choiceItem];
1657
1658 {
1659 if ( cursorIndex == wxCURSOR_NONE )
1660 cursorIndex = wxCURSOR_ARROW;
1661
1662 wxCursor cursor( cursorIndex );
1663
1664 #ifdef __WXMSW__
1665 HDC hDc = (HDC)((const wxMSWDCImpl *)dc.GetImpl())->GetHDC();
1666 ::DrawIconEx( hDc,
1667 rect.x,
1668 rect.y,
1669 (HICON)cursor.GetHandle(),
1670 0,
1671 0,
1672 0,
1673 NULL,
1674 #if !defined(__WXWINCE__)
1675 DI_COMPAT | DI_DEFAULTSIZE |
1676 #endif
1677 DI_NORMAL
1678 );
1679 #endif
1680 }
1681 }
1682 }
1683 }
1684
1685 #else
1686 void wxCursorProperty::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { }
1687 /*wxPGCellRenderer* wxCursorProperty::GetCellRenderer( int column ) const
1688 {
1689 return wxEnumProperty::GetCellRenderer(column);
1690 }*/
1691 #endif
1692
1693 // -----------------------------------------------------------------------
1694 // wxImageFileProperty
1695 // -----------------------------------------------------------------------
1696
1697 #if wxUSE_IMAGE
1698
1699 const wxString& wxPGGetDefaultImageWildcard()
1700 {
1701 // Form the wildcard, if not done yet
1702 if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() )
1703 {
1704
1705 wxString str;
1706
1707 // TODO: This section may require locking (using global).
1708
1709 wxList& handlers = wxImage::GetHandlers();
1710
1711 wxList::iterator node;
1712
1713 // Let's iterate over the image handler list.
1714 //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() )
1715 for ( node = handlers.begin(); node != handlers.end(); ++node )
1716 {
1717 wxImageHandler *handler = (wxImageHandler*)*node;
1718
1719 wxString ext_lo = handler->GetExtension();
1720 wxString ext_up = ext_lo.Upper();
1721
1722 str.append( ext_up );
1723 str.append( wxT(" files (*.") );
1724 str.append( ext_up );
1725 str.append( wxT(")|*.") );
1726 str.append( ext_lo );
1727 str.append( wxT("|") );
1728 }
1729
1730 str.append ( wxT("All files (*.*)|*.*") );
1731
1732 wxPGGlobalVars->m_pDefaultImageWildcard = str;
1733 }
1734
1735 return wxPGGlobalVars->m_pDefaultImageWildcard;
1736 }
1737
1738 IMPLEMENT_DYNAMIC_CLASS(wxImageFileProperty, wxFileProperty)
1739
1740 wxImageFileProperty::wxImageFileProperty( const wxString& label, const wxString& name,
1741 const wxString& value )
1742 : wxFileProperty(label,name,value)
1743 {
1744 SetAttribute( wxPG_FILE_WILDCARD, wxPGGetDefaultImageWildcard() );
1745
1746 m_pImage = (wxImage*) NULL;
1747 m_pBitmap = (wxBitmap*) NULL;
1748 }
1749
1750 wxImageFileProperty::~wxImageFileProperty()
1751 {
1752 if ( m_pBitmap )
1753 delete m_pBitmap;
1754 if ( m_pImage )
1755 delete m_pImage;
1756 }
1757
1758 void wxImageFileProperty::OnSetValue()
1759 {
1760 wxFileProperty::OnSetValue();
1761
1762 // Delete old image
1763 if ( m_pImage )
1764 {
1765 delete m_pImage;
1766 m_pImage = NULL;
1767 }
1768 if ( m_pBitmap )
1769 {
1770 delete m_pBitmap;
1771 m_pBitmap = NULL;
1772 }
1773
1774 wxFileName filename = GetFileName();
1775
1776 // Create the image thumbnail
1777 if ( filename.FileExists() )
1778 {
1779 m_pImage = new wxImage( filename.GetFullPath() );
1780 }
1781 }
1782
1783 wxSize wxImageFileProperty::OnMeasureImage( int ) const
1784 {
1785 return wxPG_DEFAULT_IMAGE_SIZE;
1786 }
1787
1788 void wxImageFileProperty::OnCustomPaint( wxDC& dc,
1789 const wxRect& rect,
1790 wxPGPaintData& )
1791 {
1792 if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) )
1793 {
1794 // Draw the thumbnail
1795
1796 // Create the bitmap here because required size is not known in OnSetValue().
1797 if ( !m_pBitmap )
1798 {
1799 m_pImage->Rescale( rect.width, rect.height );
1800 m_pBitmap = new wxBitmap( *m_pImage );
1801 delete m_pImage;
1802 m_pImage = NULL;
1803 }
1804
1805 dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false );
1806 }
1807 else
1808 {
1809 // No file - just draw a white box
1810 dc.SetBrush( *wxWHITE_BRUSH );
1811 dc.DrawRectangle ( rect );
1812 }
1813 }
1814
1815 #endif // wxUSE_IMAGE
1816
1817 // -----------------------------------------------------------------------
1818 // wxMultiChoiceProperty
1819 // -----------------------------------------------------------------------
1820
1821 #if wxUSE_CHOICEDLG
1822
1823 #include "wx/choicdlg.h"
1824
1825 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxPGProperty,
1826 wxArrayInt,const wxArrayInt&,TextCtrlAndButton)
1827
1828 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1829 const wxString& name,
1830 const wxPGChoices& choices,
1831 const wxArrayString& value)
1832 : wxPGProperty(label,name)
1833 {
1834 m_choices.Assign(choices);
1835 SetValue(value);
1836 }
1837
1838 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1839 const wxString& name,
1840 const wxArrayString& strings,
1841 const wxArrayString& value)
1842 : wxPGProperty(label,name)
1843 {
1844 m_choices.Set(strings);
1845 SetValue(value);
1846 }
1847
1848 wxMultiChoiceProperty::wxMultiChoiceProperty( const wxString& label,
1849 const wxString& name,
1850 const wxArrayString& value)
1851 : wxPGProperty(label,name)
1852 {
1853 wxArrayString strings;
1854 m_choices.Set(strings);
1855 SetValue(value);
1856 }
1857
1858 wxMultiChoiceProperty::~wxMultiChoiceProperty()
1859 {
1860 }
1861
1862 void wxMultiChoiceProperty::OnSetValue()
1863 {
1864 GenerateValueAsString(m_value, &m_display);
1865 }
1866
1867 wxString wxMultiChoiceProperty::ValueToString( wxVariant& value,
1868 int argFlags ) const
1869 {
1870 // If possible, use cached string
1871 if ( argFlags & wxPG_VALUE_IS_CURRENT )
1872 return m_display;
1873
1874 wxString s;
1875 GenerateValueAsString(value, &s);
1876 return s;
1877 }
1878
1879 void wxMultiChoiceProperty::GenerateValueAsString( wxVariant& value,
1880 wxString* target ) const
1881 {
1882 wxArrayString strings;
1883
1884 if ( value.GetType() == wxPG_VARIANT_TYPE_ARRSTRING )
1885 strings = value.GetArrayString();
1886
1887 wxString& tempStr = *target;
1888 unsigned int i;
1889 unsigned int itemCount = strings.size();
1890
1891 tempStr.Empty();
1892
1893 if ( itemCount )
1894 tempStr.append( wxT("\"") );
1895
1896 for ( i = 0; i < itemCount; i++ )
1897 {
1898 tempStr.append( strings[i] );
1899 tempStr.append( wxT("\"") );
1900 if ( i < (itemCount-1) )
1901 tempStr.append ( wxT(" \"") );
1902 }
1903 }
1904
1905 wxArrayInt wxMultiChoiceProperty::GetValueAsIndices() const
1906 {
1907 wxVariant variant = GetValue();
1908 const wxArrayInt& valueArr = wxArrayIntRefFromVariant(variant);
1909 unsigned int i;
1910
1911 // Translate values to string indices.
1912 wxArrayInt selections;
1913
1914 if ( !m_choices.IsOk() || !m_choices.GetCount() || !(&valueArr) )
1915 {
1916 for ( i=0; i<valueArr.size(); i++ )
1917 selections.Add(-1);
1918 }
1919 else
1920 {
1921 for ( i=0; i<valueArr.size(); i++ )
1922 {
1923 int sIndex = m_choices.Index(valueArr[i]);
1924 if ( sIndex >= 0 )
1925 selections.Add(sIndex);
1926 }
1927 }
1928
1929 return selections;
1930 }
1931
1932 bool wxMultiChoiceProperty::OnEvent( wxPropertyGrid* propgrid,
1933 wxWindow* WXUNUSED(primary),
1934 wxEvent& event )
1935 {
1936 if ( propgrid->IsMainButtonEvent(event) )
1937 {
1938 // Update the value
1939 wxVariant useValue = propgrid->GetUncommittedPropertyValue();
1940
1941 wxArrayString labels = m_choices.GetLabels();
1942 unsigned int choiceCount;
1943
1944 if ( m_choices.IsOk() )
1945 choiceCount = m_choices.GetCount();
1946 else
1947 choiceCount = 0;
1948
1949 // launch editor dialog
1950 wxMultiChoiceDialog dlg( propgrid,
1951 _("Make a selection:"),
1952 m_label,
1953 choiceCount,
1954 choiceCount?&labels[0]:NULL,
1955 wxCHOICEDLG_STYLE );
1956
1957 dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) );
1958
1959 wxArrayString strings = useValue.GetArrayString();
1960 wxArrayString extraStrings;
1961
1962 dlg.SetSelections(m_choices.GetIndicesForStrings(strings, &extraStrings));
1963
1964 if ( dlg.ShowModal() == wxID_OK && choiceCount )
1965 {
1966 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
1967
1968 wxArrayInt arrInt = dlg.GetSelections();
1969
1970 wxVariant variant;
1971
1972 // Strings that were not in list of choices
1973 wxArrayString value;
1974
1975 // Translate string indices to strings
1976
1977 unsigned int n;
1978 if ( userStringMode == 1 )
1979 {
1980 for (n=0;n<extraStrings.size();n++)
1981 value.push_back(extraStrings[n]);
1982 }
1983
1984 unsigned int i;
1985 for ( i=0; i<arrInt.size(); i++ )
1986 value.Add(m_choices.GetLabel(arrInt.Item(i)));
1987
1988 if ( userStringMode == 2 )
1989 {
1990 for (n=0;n<extraStrings.size();n++)
1991 value.push_back(extraStrings[n]);
1992 }
1993
1994 variant = WXVARIANT(value);
1995
1996 SetValueInEvent(variant);
1997
1998 return true;
1999 }
2000 }
2001 return false;
2002 }
2003
2004 bool wxMultiChoiceProperty::StringToValue( wxVariant& variant, const wxString& text, int ) const
2005 {
2006 wxArrayString arr;
2007
2008 int userStringMode = GetAttributeAsLong(wxT("UserStringMode"), 0);
2009
2010 WX_PG_TOKENIZER2_BEGIN(text,wxT('"'))
2011 if ( userStringMode > 0 || (m_choices.IsOk() && m_choices.Index( token ) != wxNOT_FOUND) )
2012 arr.Add(token);
2013 WX_PG_TOKENIZER2_END()
2014
2015 wxVariant v( WXVARIANT(arr) );
2016 variant = v;
2017
2018 return true;
2019 }
2020
2021 #endif // wxUSE_CHOICEDLG
2022
2023
2024 // -----------------------------------------------------------------------
2025 // wxDateProperty
2026 // -----------------------------------------------------------------------
2027
2028 #if wxUSE_DATETIME
2029
2030
2031 #if wxUSE_DATEPICKCTRL
2032 #define dtCtrl DatePickerCtrl
2033 #else
2034 #define dtCtrl TextCtrl
2035 #endif
2036
2037 WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty,
2038 wxPGProperty,
2039 wxDateTime,
2040 const wxDateTime&,
2041 dtCtrl)
2042
2043
2044 wxString wxDateProperty::ms_defaultDateFormat;
2045
2046
2047 wxDateProperty::wxDateProperty( const wxString& label,
2048 const wxString& name,
2049 const wxDateTime& value )
2050 : wxPGProperty(label,name)
2051 {
2052 //wxPGRegisterDefaultValueType(wxDateTime)
2053
2054 #if wxUSE_DATEPICKCTRL
2055 wxPGRegisterEditorClass(DatePickerCtrl);
2056
2057 m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY;
2058 #else
2059 m_dpStyle = 0;
2060 #endif
2061
2062 SetValue( value );
2063 }
2064
2065 wxDateProperty::~wxDateProperty()
2066 {
2067 }
2068
2069 bool wxDateProperty::StringToValue( wxVariant& variant, const wxString& text,
2070 int WXUNUSED(argFlags) ) const
2071 {
2072 wxDateTime dt;
2073
2074 const char* c = dt.ParseFormat(text, wxString(wxDefaultDateTimeFormat), wxDefaultDateTime, NULL);
2075
2076 if ( c )
2077 {
2078 variant = dt;
2079 return true;
2080 }
2081
2082 return false;
2083 }
2084
2085 wxString wxDateProperty::ValueToString( wxVariant& value,
2086 int argFlags ) const
2087 {
2088 const wxChar* format = (const wxChar*) NULL;
2089
2090 wxDateTime dateTime = value.GetDateTime();
2091
2092 if ( !dateTime.IsValid() )
2093 return wxT("Invalid");
2094
2095 if ( !ms_defaultDateFormat.length() )
2096 {
2097 #if wxUSE_DATEPICKCTRL
2098 bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false;
2099 #else
2100 bool showCentury = true;
2101 #endif
2102 ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury );
2103 }
2104
2105 if ( m_format.length() &&
2106 !(argFlags & wxPG_FULL_VALUE) )
2107 format = m_format.c_str();
2108
2109 // Determine default from locale
2110 // NB: This is really simple stuff, but can't figure anything
2111 // better without proper support in wxLocale
2112 if ( !format )
2113 format = ms_defaultDateFormat.c_str();
2114
2115 return dateTime.Format(format);
2116 }
2117
2118 wxString wxDateProperty::DetermineDefaultDateFormat( bool showCentury )
2119 {
2120 // This code is basicly copied from datectlg.cpp's SetFormat
2121 //
2122 wxString format;
2123
2124 wxDateTime dt;
2125 dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d"));
2126 wxString str(dt.Format(wxT("%x")));
2127
2128 const wxChar *p = str.c_str();
2129 while ( *p )
2130 {
2131 int n=wxAtoi(p);
2132 if (n == dt.GetDay())
2133 {
2134 format.Append(wxT("%d"));
2135 p += 2;
2136 }
2137 else if (n == (int)dt.GetMonth()+1)
2138 {
2139 format.Append(wxT("%m"));
2140 p += 2;
2141 }
2142 else if (n == dt.GetYear())
2143 {
2144 format.Append(wxT("%Y"));
2145 p += 4;
2146 }
2147 else if (n == (dt.GetYear() % 100))
2148 {
2149 if (showCentury)
2150 format.Append(wxT("%Y"));
2151 else
2152 format.Append(wxT("%y"));
2153 p += 2;
2154 }
2155 else
2156 format.Append(*p++);
2157 }
2158
2159 return format;
2160 }
2161
2162 bool wxDateProperty::DoSetAttribute( const wxString& name, wxVariant& value )
2163 {
2164 if ( name == wxPG_DATE_FORMAT )
2165 {
2166 m_format = value.GetString();
2167 return true;
2168 }
2169 else if ( name == wxPG_DATE_PICKER_STYLE )
2170 {
2171 m_dpStyle = value.GetLong();
2172 ms_defaultDateFormat.clear(); // This may need recalculation
2173 return true;
2174 }
2175 return false;
2176 }
2177
2178 #endif // wxUSE_DATETIME
2179
2180
2181 // -----------------------------------------------------------------------
2182 // wxPropertyGridInterface
2183 // -----------------------------------------------------------------------
2184
2185 void wxPropertyGridInterface::InitAllTypeHandlers()
2186 {
2187 }
2188
2189 // -----------------------------------------------------------------------
2190
2191 void wxPropertyGridInterface::RegisterAdditionalEditors()
2192 {
2193 // Register editor classes, if necessary.
2194 if ( wxPGGlobalVars->m_mapEditorClasses.empty() )
2195 wxPropertyGrid::RegisterDefaultEditors();
2196
2197 #if wxUSE_SPINBTN
2198 wxPGRegisterEditorClass(SpinCtrl);
2199 #endif
2200 #if wxUSE_DATEPICKCTRL
2201 wxPGRegisterEditorClass(DatePickerCtrl);
2202 #endif
2203 }
2204
2205 // -----------------------------------------------------------------------
2206
2207 #endif // wxPG_INCLUDE_ADVPROPS
2208
2209 #endif // wxUSE_PROPGRID
2210